18 min read

Python 基础

Python 基础
Photo by Barbare Kacharava / Unsplash
  • # 一级标题是大的板块
  • ## 二级标题是该板块的分类
  • ### 三级标题是重要知识点
  • 每一章加入开头有英文总结模块,帮助提升英文环境编程能力

参考资料:

1. Python 官方教程

2. Python基础:从入门到实践

import this

"""ouptut
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
"""

一、Python开发环境

Python 是 C 语言写的,具有很强的可移植性


配置 Python 环境

包的安装

[!tips] pip 和 pip3 的区别pip 是 Python 2 或 Python 3 的包管理工具,取决于系统环境;pip3 仅针对 Python 3。
# 安装包
pip3 install <package>
pip3 install pandas

# 安装特定版本包
pip3 install <package> == <version>
pip3 install numpy==1.21.0

# 升级包
pip3 install --upgrade <包名>
pip3 install --upgrade numpy

# 网络问题
# 有时候会发现,断开 VPN 才是解决网络问题的最好方法
pip install  <package> -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

# 网络问题2
pip config unset global.index-url && conda activate quant && python3 -m pip install PyQt6


# 其他镜像源
- https://pypi.douban.com/simple/
- https://mirrors.aliyun.com/pypi/simple/
- https://mirrors.163.com/pypi/simple/
- https://mirrors.aliyun.com/pypi/simple/

如何查看 mac 中 python3 的安装路径

where python3
result
/Library/Frameworks/Python.framework/Versions/3.10/bin/python3
/usr/local/bin/python3
/usr/bin/python3
  • 或者
python3
import sys
sys.path
result
['', '/Library/Frameworks/Python.framework/Versions/3.10/lib/python310.zip', '/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10', '/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/lib-dynload', '/Users/username/Library/Python/3.10/lib/python/site-packages', '/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages']
cd /Library/Frameworks/Python.framework/Versions/3.10
ls
result
Headers Resources bin include share
Python _CodeSignature etc lib

python 虚拟环境

[!tips]
参考链接:安装不算完事,只有理解了虚拟环境才算真正掌握 Python 环境
[!notes]Python 虚拟环境的作用是:对特定项目使用特定版本的包,从而项目之间不会互相影响。不同版本的包之间不会发生冲突

使用步骤

使用介绍

python3 -m venv -h


<!--
1. python3
这是用于调用 Python 3 的可执行命令。
作用:明确告诉系统我们要使用 Python 3 的解释器,而不是其他版本(如 Python 2)。

2. -m venv
	• -m 表示以模块(module)的方式运行 Python,紧随其后的 venv 是模块的名称。
	• venv 是 Python 的一个模块,用于创建虚拟环境。
作用:告诉 Python 执行 venv 模块中的功能,而不是运行某个文件。

3. -h
这是命令行选项,通常表示 help(帮助)。
作用:当与 venv 模块一起使用时,显示其支持的命令和选项。
-->
# 用法
usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
            [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps]
            ENV_DIR [ENV_DIR ...]

# 在一个或多个目标目录中创建虚拟Python环境。
Creates virtual Python environments in one or more target directories.

# ENV_DIR 是一个位置参数,表示虚拟环境的目录。你可以指定一个或多个目录名称,venv 将会在这些目录中创建虚拟环境。
positional arguments:
  ENV_DIR               A directory to create the environment in.

# 可选项有哪些
options:

# 显示帮助信息(如当前内容),然后退出命令。
  -h, --help            show this help message and exit
  
# 默认false,启用后,虚拟环境将包含对全局(系统级)Python包的访问权限。这意味着虚拟环境可以直接使用系统安装的 Python 包,而不需要重新安装
  --system-site-packages
                        Give the virtual environment access to the system
                        site-packages dir.
                        
# 默认选项。虚拟环境中的二进制文件会通过符号链接指向系统的 Python 安装,而不是复制文件。
  --symlinks            Try to use symlinks rather than copies, when symlinks
                        are not the default for the platform.
  --copies              Try to use copies rather than symlinks, even when
                        symlinks are the default for the platform.
  --clear               Delete the contents of the environment directory if it
                        already exists, before environment creation.

# 如果虚拟环境已经存在,该选项会更新其配置和内容,而不是重新创建整个环境。
  --upgrade             Upgrade the environment directory to use this version
                        of Python, assuming Python has been upgraded in-place.
  --without-pip         Skips installing or upgrading pip in the virtual
                        environment (pip is bootstrapped by default)
  --prompt PROMPT       Provides an alternative prompt prefix for this
                        environment.
  --upgrade-deps        Upgrade core dependencies: pip setuptools to the
                        latest version in PyPI

# 创建环境后,您可能希望激活它,例如通过在其bin目录中获取激活脚本。
Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.
virtualenv -p /usr/bin/pythonx.x myenv
conda activate base
<!--
安装指定版本 Python 版本的虚拟环境
-->

创建虚拟环境

  • 在 当前目录创建一个 虚拟环境文件夹 venvdemo
python3 -m venv venvdemo
source bin/activate

# 关闭虚拟环境使用 deactivate
  • 在虚拟环境,下调用一下 python
python
  • 看看现在的 python 路径有哪些
import sys
from pprint import pprint
pprint(sys.path)
  • 可以发现最后一行就是虚拟环境下的 python
['',
 '/Library/Frameworks/Python.framework/Versions/3.10/lib/python310.zip',
 '/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10',
 '/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/lib-dynload',
 '/Users/jaylorden/venvdemo/lib/python3.10/site-packages']

虚拟环境的导出

# 查看安装列表
pip list

# 导出版本信息到 requirements.txt
pip freeze > requirements.txt

# 安装目标库
pip install -r requirements.txt
blinker==1.9.0
click==8.1.7
Flask==3.1.0
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==3.0.2
Werkzeug==3.1.3

vscode 中使用虚拟环境

  • vscode 现在支持直接在选择解释器界面创建虚拟环境。
  • 当然,这样的工作流程就会和终端创建虚拟环境会有所差异,而后者是通用的,建议掌握熟练之后再使用 vscode 界面、快捷的创建方式。
个人还是偏向于一个项目一个虚拟环境,因此在每个项目文件夹中创建虚拟环境即可;一个好的文件夹逻辑:项目文件.venv文件夹项目内容
这时候,将项目文件拖入 vscode 中,.venv1 中的 python 就会被自动识别了。

conda 使用

  1. 激活 conda 的 base 虚拟环境
conda activate base

二、数据类型和变量

Datatype: 数据类型;区分Data Structure 数据结构

字符串

Python 中单双引号没有差异,灵活运用单双引号很好地输出

s1 = 'I told my friend, "Python is my favorite language!"'
s2 = "The language 'Python' is named after Monty Python, not the snake."
s3 = "One of Python's strengths is its diverse and supportive community."
print(s1, s2, s3)

# output
'''
I told my friend, "Python is my favorite language!" 
The language 'Python' is named after Monty Python, not the snake. 
One of Python's strengths is its diverse and supportive community.
'''

对于字符,Python 仅仅只有字符串这这一种数据类型,而像 Java、C++ 等还有字符型数据类型

char c1 = 'A'
String s1 = "ABC"
string1 = 'A'
string2 = 'ABC'
print(string1, string2)

# output:
# A ABC

字符串的一些内置函数

方法 效果
str = str.upper() 全部转为大写
str = str.lower() 全部转为小谢
str = str.strip() 去除两端的空格
list = str.split(sep) 根据制定分隔符,将字符串拆分成列表
str = str.join(iterable)# 可迭代对象中的字符串连接成一个新的字符串
int = str.find(sub) 返回字符串首次出现的索引
str = str.replace(old, new) 替换字符串中的元素
bool = str.startswith(prefix) 判断字符串是否以 profix 开头
bool = str.endswith(suffix) 判断字符串的后缀是否是 suffix
int = str.count(sub) 统计 str 中 sub 的个数
str = str.capitalize() 大写 str 的首字母
bool = isdigit() 判断是否数字开头
str = str.format() 格式化字符串
# 挑几个不那么显而易见的跑一跑

# 1. split()
s1 = "I'm listening kendrick lamar's songs."
s1_1 = s1.split( )
print(s1_1)
'''output
["I'm", 'listening', 'kendrick', "lamar's", 'songs.']
'''

# 2. find()
s2 = "Hello, world!"
index1 = s2.find("world")  
index2 = s2.find('w')
print(index1, index2)
'''output
7 7
'''
# 解释:查找 world 和查找 w 是一样的效果

# 3. join()
words = ["hello", "world"]
result = ",".join(words)  
'''output:
'hello,world'
'''
讲完字符串讲 print,别提有多合适了。下面对 print() 方法的常见用法进行总结归纳:
  1. 打印多个值
x = 10
y = 20
print("x =", x, "y =", y)

"""output
x = 10 y = 20
"""
# 解释:这里实则是一次性打印了四个值,两个字符串、两个变量
  1. 添加分隔符
print("Apple", "Banana", "Cherry", sep=", ")

"""output
Apple, Banana, Cherry
"""
# 如果不加 sep 参数,得到的将是 Apple Banana Cherry
  1. 添加结尾
print("Hello", end=" ")
print("World!")

"""output
Hello World!
"""
# 解释:如果不加 end 参数,两行打印将会换行
  1. 打印到文件中
with open("output.txt", "w") as f:
    print("This is a test", file=f)
    
# 将在 py 同级文件下产生一个 output.txt 文件,并将内容
# “This is a test” 写入到该文件中
  1. 格式化输出
name = "lorde"
age = 28
print(f"My name is {name} and I am {age} years old.")
print("My name is {} and I am {} years old.".format(name, age))

"""output
My name is lorde and I am 28 years old.
My name is lorde and I am 28 years old.
"""
  1. 打印转义字符
其实这并不是 print() 直接的知识点,但二者结合使用的概率很大
print("Line 1\nLine 2")  # \n:换行符
print("Column1\tColumn2")  # \t:制表符

"""output
Line 1
Line 2
Column1	Column2
"""
# 补充:制表符这个概念,本质是多个空格,作用是对齐,差别是不同 IDE 中,宽度会有所不同—-

input 函数

  • input(prompt) 是可以放参数的,不要只写字在括号里了
prompt = "If you tell us who you are, we can personalize the messages you see."
prompt += "\nWhat is your first name?\n"

name = input(prompt)
print('Hello, ' + name.title() + '!')
"""output
If you tell us who you are, we can personalize the messages you see.
What is your first name?
Jay
Hello, Jay!
"""
  • 千万别忘了 input() 的返回值是 str(虽然说了还是经常会忘)

正则表达式

regular expression,爬虫、ID验证、文本搜索等场景下使用频率高。

![[%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.png]]


数字类型

  • 关于小数点

之前一直忽略一个细节:

print(0.2*0.1) # output:0.020000000000000004

其实许多编程语言的小数计算都会存在小数位数不确定的情况。

  • 关于数值和字符串

数值和字符串混用是 Python 中经常容易出现的 bug,特别是在值传递和字符串连接的时候尤其需要注意这一点。因此 str()int() 的使用就尤其重要。

  • 运算符
    • 求模运算:%
      • 返回两个数相除后的余数
    • 除法取整://

列表

一个非常实用的数据类型,中括号中可以存放多种类型的数据

列表属于 Python 的可迭代对象,另外还有range、字符串、元组、字典、集合、生成器、文件对象、Numpy数组

用法

方法 效果
创建
list = [] 创建空列表
list = list(range(start=0, stop, step=1)) range 生成
new_list = [expression for item in iterable if condition] 列表生成式
list = list.append() 在列表末尾添加一个元素
list = list.extend() 将一个可迭代对象的元素添加到列表末尾
list = list.insert() 在指定位置之前插入一个元素
del list(index) (根据位置)
list = list.remove() (根据值)删除列表中第一个匹配的元素
list.pop() (根据位置)移除并返回指定位置的元素(默认为最后一个元素)
NoneType = ls.clear() 移除列表中的所有元素
list = list.sort(reverse=False) 对列表进行排序,默认由小到大
list = list.sorted() 临时排序(不改变原列表)
list = list.reverse() 反转列表
int = list.index() 返回指定元素第一次出现的索引。
int = list.count() 返回指定元素在列表中出现的次数。
len = len(list) 列表长度
fac = min(list) 列表中的最小值
fac = max(list) 列表中的最大值
fac = sum(list) 列表总和(元素为数值时)
list = list[start, stop, step] 切片
# 挑几个不那么显而易见的跑一跑

# 1. extend()
my_list = [1, 2, 3]
my_list.extend([4, 5])  # my_list 变为 [1, 2, 3, 4, 5]

# 2. find()
my_list = [1, 2, 3]
my_list.insert(1, 1.5)  # my_list 变为 [1, 1.5, 2, 3]
# 注意是,插入在该元素之前

# 3. sort()
ls = ['Omen', 'Jett', 'Breach']
ls.sort()  # ls 变为 ['Breach', 'Jett', 'Omen']
# 字符串也能排序,按照 ASCII 表进行排列

# 4. 列表生成式
sqrs = [x**2 for x in range(1, 11) if x % 2 == 0] # [4, 16, 36, 64, 100]

元组

教材将元组看作特殊的列表
  • 许多列表适用的方法,元组同样适用
  • 下面介绍一下差别
    • 元组是小括号组成的
    • 元组元素是不可更改的
    • 可以通过重新定义元组来改变元组

练习

  1. 使用列表打印 99乘法表
for i in range(1, 10):
    for j in range(1, i+1):
        print('{}*{}={}\t'.format(i, j, j*i), end='')
    print()

字典

最适合描述世界的数据类型

用法

方法 效果
创建
dict = {key: value} 白手起家
dict[new_key] = value 在 dict 中添加新的键值对,即 new_key: value
dict.update(other_dict) 根据 other_dict 对 dict 进行更新
dict.pop(key, default=None) 根据 key 删除 dict 中的元素,如果不存在,返回第二个参数
dict.clear() 删除 dict 中所有的键值对
del dict[’key’] 根据 key 删除 dict 中的元素
dict[key] = new_value 将 dict 中键 key 的值改为 new_value
sort(dict, reverse=False) 正序(由小到大),改变原字典
sorted(dict, reverse=False) 正序(由小到大),不改变原字典
dict.get(key, default=None) 返回对应键的值,如果不存在返回第二个参数,默认为None
dict.keys() 返回字典的所有键的视图(视图vs副本:视图随原字典的变化而变化)
dict.values() 返回字典的所有值的视图
dict.items() 返回字典的所有键值对的视图
dict[’key’] 根据键索引

嵌套

  • 列表中放字典
“alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}

aliens = [alien_0, alien_1, alien_2]
  • 字典中放列表
favorite_languages = { 
    'jen': ['python', 'ruby'],
    'sarah': ['c'],
    'edward': ['ruby', 'go'],
    'phil': ['python', 'haskell'],
    }
  • 字典中放字典
users = {
    'aeinstein': {
        'first': 'albert',
        'last': 'einstein',”
        'location': 'princeton',
        },

    'mcurie': {
        'first': 'marie',
        'last': 'curie',
        'location': 'paris',
        },
        
    }

三、Python的逻辑语句

if 语句

也不知道能学些啥新东西
if condition_1:
  	do sth
elif condition_2:
    do another thing
···
else condition_n:
		do other things
  • == 其实是一个问句,a == 3 意思是:a的值等于3吗?,因此返回值就是 True 或者 False
  • 如果经常记不住判断相等需要==而不是= ,可以类比,毕竟表示不等!= 也需要两个符号
  • 多个条件:一个 if 后可以根多个条件,使用 andor 连接
  • in 关键字:用于检查某个元素是否在序列中

while 语句

  • 似乎没有什么特别的用法了。
while condition_1:
		do sth
		if condition_2:
				continue
				
		do sth
		
		if condition_3:
				break

四、函数

  • 打印函数的文档字符串(docstring): function.__doc__
print(print.__doc__)
"""output
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
"""
  • 而文档字符串又是怎么写的呢:写在函数定义的下一行,须用三引号包裹
def greet_user(username):
    """显示简单的问候语"""
    print("Hello, " + username.title() + "!")

print(greet_user.__doc__)
"""output
显示简单的问候语
"""

参数传递

  • 实参和形参

区别一下概念:形参是在函数定义时指定的变量;实参是在函数调用时实际传递给函数的值

比如上一个例子中,username 是形参,greet_user(’Jay’)中,‘Jay’ 就是实参

  • 参数传递的方法
  1. 位置传递

实参的顺序需要和形参对应

  1. 关键字传递

不要求实参顺序,只要关键字和形参对应即可

def greet_user(username, age):
    print(username + str(age))

greet_user(age=23, username='jay')
  1. 可以将列表作为实参进行传递

注意:此时会改变列表。传递列表的副本可以避免,例如传入 ls[:]

  • 传递任意数量实参的形参
    • 使用元组形参,例如 def printDog(*dogs) *dogs 会将实参全部封装到 dogs 元组中
    • 为了避免错误封装,能传递任意数量实参的形参需要放在所有形参的最后

返回值

  • 返回值并非必须
  • 返回值可以是字典等

导入特定模块的函数

  • import module_name
  • import module_name as mn
  • from module_name import function_name_1, function_name_2, ...
  • from module_name import *

五、文件

六、异常


try:
		do sth
except errorType:
		do sth
else:
		do sth
  • 概述
    • 异常也是一个对象
    • 编写异常处理代码,使得 Python 代码再遇到错误时能够继续运行
    • 异常处理让用户看到适合他们看到的内容,否则就会出现用户看不懂、用户窃取内部代码等情况
  • 未使用异常处理:
print(5/0)
"""ouput
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[3], line 1
----> 1 print(5/0)

ZeroDivisionError: division by zero
"""
  • 使用异常处理
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
"""output
You can't divide by zero!
"""

七、测试

用 Python 模块 unittest 中的工具来测试代码

断言


  • “断言”是 unittest 类最有用的功能之一
  • 通过预输入结果结果与真实结果比较,产生不同的输入和输出
文件树

- test
    - name_function.py
    - names.py
    - test_name_function.py

name_function.py :定义函数

def get_formatted_name(first, last):
    """Generate a neatly formatted full name."""
    full_name = first + ' ' + last
    return full_name.title()

names.py:主函数

from name_function import get_formatted_name

print("Enter 'q' at any time to quit.")
while True:
    first = input("\nPlease give me a first name: ")
    if first == 'q':
        break
    last = input("Please give me a last name: ")
    if last == 'q':
        break

    formatted_name = get_formatted_name(first, last)
    print("\tNeatly formatted name: " + formatted_name + '.')

test_name_function.py :测试函数

import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""

    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

result.txt

# pass
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK



# not pass,随便修改了一点错误出来
F
======================================================================
FAIL: test_first_last_name (__main__.NamesTestCase)
能够正确地处理像Janis Joplin这样的姓名吗?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/hetao/Desktop/test/test_name_function.py", line 10, in test_first_last_name
    self.assertEqual(formatted_name, 'Janis  Joplin')
AssertionError: 'Janis Joplin' != 'Janis  Joplin'
- Janis Joplin
+ Janis  Joplin
?      +


----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)
  • 一些断言方法
方法 作用
assertEqual(a, b) 核实a == b
assertNotEqual(a, b) 核实a != b
assertTrue(x) 核实x为True
assertFalse(x) 核实x为False
assertIn(item, list) 核实item在list中
assertNotIn(item, list) 核实item不在list中
i