基于 Python 3.12+(当前主流生产版本),标注了 3.10/3.11/3.12 引入的新语法。
参考来源:Python 官方语言参考、Python 官方教程、PEP 文档。
一、变量与数据类型
1.1 变量赋值
# 单变量赋值
x = 10
name = "Alice"
# 多变量同时赋值
a, b, c = 1, 2, 3
# 多变量相同值
x = y = z = 0
# 解包赋值
first, *rest = [1, 2, 3, 4, 5] # first=1, rest=[2,3,4,5]
*head, last = [1, 2, 3, 4, 5] # head=[1,2,3,4], last=5
first, *middle, last = [1, 2, 3, 4, 5] # first=1, middle=[2,3,4], last=5
# 交换变量(不需要临时变量)
a, b = b, a
1.2 数据类型总览
| 类型 | 说明 | 示例 |
|---|---|---|
int | 整数,无大小限制 | 42, -7, 10**100 |
float | 64 位双精度浮点数 | 3.14, 1e10, float('inf') |
complex | 复数 | 3+4j, complex(1, 2) |
bool | 布尔值(int 的子类) | True, False |
str | Unicode 字符串(不可变) | "hello", 'world' |
bytes | 字节串(不可变) | b"hello", bytes([65, 66]) |
bytearray | 字节串(可变) | bytearray(b"hello") |
NoneType | 空值 | None |
1.3 类型检查与转换
# 类型检查
type(42) # <class 'int'>
isinstance(42, int) # True
isinstance(True, int) # True(bool 是 int 的子类)
# 类型转换
int("42") # 42
int(3.9) # 3(截断,不是四舍五入)
float("3.14") # 3.14
str(42) # "42"
bool(0) # False
bool("") # False
bool([]) # False
bool(None) # False
bool("hello") # True
bool([1, 2]) # True
⚠️ Python 是动态类型语言:变量没有类型声明,类型绑定在对象上而非变量上。同一个变量可以先后绑定不同类型的对象。
1.4 数值运算
# 算术运算
10 / 3 # 3.333...(真除法,始终返回 float)
10 // 3 # 3(整除/地板除)
10 % 3 # 1(取模)
2 ** 10 # 1024(幂运算)
# 比较运算
x == y # 值相等
x != y # 值不等
x is y # 同一对象(身份比较)
x is not y # 不同对象
# 链式比较(Python 独有语法糖)
1 < x < 10 # 等价于 1 < x and x < 10
a <= b < c # 等价于 a <= b and b < c
# 位运算
5 & 3 # 1(按位与)
5 | 3 # 7(按位或)
5 ^ 3 # 6(按位异或)
~5 # -6(按位取反)
5 << 1 # 10(左移)
5 >> 1 # 2(右移)
1.5 海象运算符(Python 3.8+)
# := 在表达式中赋值
import re
if (match := re.search(r'\d+', "abc123def")):
print(match.group()) # "123"
# 在 while 循环中使用
while (line := input(">>> ")) != "quit":
print(f"You said: {line}")
# 在列表推导式中过滤
results = [y for x in data if (y := f(x)) > 0]
二、字符串(str)
2.1 字符串创建
# 单引号、双引号(完全等价)
s1 = 'hello'
s2 = "hello"
# 三引号:多行字符串
s3 = """这是
多行
字符串"""
# 原始字符串(不处理转义)
path = r"C:\Users\name\file.txt" # 反斜杠不转义
regex = r"\d+.\d+" # 正则表达式常用
# 字节串
b = b"hello" # bytes 类型
b2 = "hello".encode("utf-8") # str → bytes
s = b.decode("utf-8") # bytes → str
2.2 f-string 格式化(Python 3.6+,3.12 大幅增强)
name = "Alice"
age = 30
pi = 3.14159265
# 基础用法
f"Hello, {name}!" # "Hello, Alice!"
f"Next year: {age + 1}" # "Next year: 31"
f"Pi: {pi:.2f}" # "Pi: 3.14"(格式化规范)
f"{'hello':>10}" # " hello"(右对齐,宽度10)
f"{'hello':<10}" # "hello "(左对齐)
f"{'hello':^10}" # " hello "(居中)
f"{42:08d}" # "00000042"(补零)
f"{1000000:,}" # "1,000,000"(千分位)
f"{0.25:.1%}" # "25.0%"(百分比)
# 调试模式(Python 3.8+)
f"{name=}" # "name='Alice'"
f"{age=}" # "age=30"
f"{pi=:.2f}" # "pi=3.14"
# Python 3.12+:表达式中可以复用引号、包含反斜杠、多行
songs = ['A', 'B', 'C']
f"Songs: {", ".join(songs)}" # "Songs: A, B, C"
f"Lines: {"\n".join(songs)}" # 反斜杠在表达式中合法
f"""{
name
.upper()
}""" # 多行表达式
2.3 字符串方法(常用)
s = " Hello, World! "
# 查找与替换
s.find("World") # 8(找不到返回 -1)
s.index("World") # 8(找不到抛 ValueError)
s.count("l") # 3
s.replace("World", "Python") # " Hello, Python! "
s.startswith(" He") # True
s.endswith("! ") # True
# 大小写
s.upper() # " HELLO, WORLD! "
s.lower() # " hello, world! "
s.title() # " Hello, World! "
s.capitalize() # " hello, world! "
s.swapcase() # " hELLO, wORLD! "
# 去除空白
s.strip() # "Hello, World!"
s.lstrip() # "Hello, World! "
s.rstrip() # " Hello, World!"
# 分割与拼接
"hello world".split() # ['hello', 'world']
"a,b,c".split(",") # ['a', 'b', 'c']
"a,b,c".split(",", maxsplit=1) # ['a', 'b,c']
",".join(["a", "b", "c"]) # "a,b,c"
# 判断
"hello".isalpha() # True(全是字母)
"123".isdigit() # True(全是数字)
"abc123".isalnum() # True(字母或数字)
" ".isspace() # True
# Python 3.9+:去除前缀/后缀
"TestHook".removeprefix("Test") # "Hook"
"TestHook".removesuffix("Hook") # "Test"
# 填充
"42".zfill(5) # "00042"
"hi".center(10, "-") # "----hi----"
"hi".ljust(10, "-") # "hi--------"
"hi".rjust(10, "-") # "--------hi"
2.4 字符串是不可变的
s = "hello"
# s[0] = "H" # ❌ TypeError: 'str' object does not support item assignment
s = "H" + s[1:] # ✅ 创建新字符串 "Hello"
三、数据结构
3.1 列表(list)—— 有序、可变、可重复
# 创建
nums = [1, 2, 3, 4, 5]
empty = []
from_range = list(range(10)) # [0, 1, 2, ..., 9]
from_str = list("hello") # ['h', 'e', 'l', 'l', 'o']
# 访问(索引从 0 开始,支持负索引)
nums[0] # 1(第一个)
nums[-1] # 5(最后一个)
nums[-2] # 4(倒数第二个)
# 切片 [start:stop:step](左闭右开)
nums[1:3] # [2, 3]
nums[:3] # [1, 2, 3](从头开始)
nums[3:] # [4, 5](到末尾)
nums[::2] # [1, 3, 5](步长2)
nums[::-1] # [5, 4, 3, 2, 1](反转)
nums[1:4:2] # [2, 4]
# 修改
nums[0] = 10 # [10, 2, 3, 4, 5]
nums[1:3] = [20, 30] # [10, 20, 30, 4, 5]
nums[1:3] = [] # [10, 4, 5](删除切片)
# 添加
nums.append(6) # 末尾添加
nums.insert(0, 0) # 指定位置插入
nums.extend([7, 8]) # 扩展(追加多个元素)
nums += [9, 10] # 等价于 extend
# 删除
nums.pop() # 删除并返回最后一个
nums.pop(0) # 删除并返回指定索引
nums.remove(10) # 删除第一个值为 10 的元素
del nums[0] # 删除指定索引
del nums[1:3] # 删除切片
nums.clear() # 清空列表
# 查找
3 in nums # True / False(成员测试)
nums.index(3) # 返回第一个匹配的索引(不存在抛 ValueError)
nums.count(3) # 出现次数
# 排序
nums.sort() # 原地排序(修改原列表)
nums.sort(reverse=True) # 降序
nums.sort(key=len) # 自定义排序键
sorted(nums) # 返回新列表,不修改原列表
sorted(nums, reverse=True)
# 其他
nums.reverse() # 原地反转
len(nums) # 长度
min(nums), max(nums) # 最小/最大值
sum(nums) # 求和(仅限数值)
list(zip([1,2], ['a','b'])) # [(1,'a'), (2,'b')]
list(enumerate(['a','b'])) # [(0,'a'), (1,'b')]
3.2 元组(tuple)—— 有序、不可变、可重复
# 创建
t = (1, 2, 3)
t2 = 1, 2, 3 # 省略括号也可以
single = (42,) # 单元素元组必须加逗号
empty = ()
from_list = tuple([1, 2, 3])
# 访问(和列表一样,支持索引和切片)
t[0] # 1
t[-1] # 3
t[1:] # (2, 3)
# 解包
a, b, c = (1, 2, 3)
first, *rest = (1, 2, 3, 4) # first=1, rest=[2,3,4]
# 命名元组(带字段名的元组)
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
p.x # 1
p.y # 2
p[0] # 1(仍然支持索引访问)
💡 何时用元组而非列表:数据不应被修改时(如坐标、数据库查询返回的行、字典的键、函数返回多个值)。元组比列表更省内存、更快,且可以作为字典的键(列表不行)。
3.3 字典(dict)—— 键值对、无序(Python 3.7+ 保证插入顺序)、键唯一
# 创建
d = {"name": "Alice", "age": 30}
d2 = dict(name="Alice", age=30)
d3 = dict([("name", "Alice"), ("age", 30)])
empty = {}
# 访问
d["name"] # "Alice"(键不存在抛 KeyError)
d.get("name") # "Alice"(键不存在返回 None)
d.get("gender", "N/A") # "N/A"(键不存在返回默认值)
# 修改/添加
d["age"] = 31 # 修改已有键
d["gender"] = "F" # 添加新键
d.update({"age": 32, "city": "Beijing"}) # 批量更新
d |= {"score": 100} # Python 3.9+:合并运算符
# 删除
del d["age"] # 删除指定键(不存在抛 KeyError)
d.pop("name") # 删除并返回值(不存在抛 KeyError)
d.pop("name", None) # 删除并返回值(不存在返回默认值)
d.popitem() # 删除并返回最后一个插入的 (key, value)
# 遍历
for key in d: # 遍历键
print(key)
for value in d.values(): # 遍历值
print(value)
for key, value in d.items(): # 遍历键值对
print(f"{key}: {value}")
# 查找
"name" in d # True(检查键是否存在)
"name" not in d # False
# 其他
len(d) # 键值对数量
list(d.keys()) # 所有键
list(d.values()) # 所有值
list(d.items()) # 所有键值对
# 字典推导式
squares = {x: x**2 for x in range(5)} # {0:0, 1:1, 2:4, 3:9, 4:16}
# Python 3.9+:合并运算符
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
d1 | d2 # {"a": 1, "b": 3, "c": 4}(d2 覆盖 d1 的同名键)
d1 |= d2 # 就地更新 d1
# defaultdict(默认值字典)
from collections import defaultdict
dd = defaultdict(list)
dd["fruits"].append("apple") # 不需要先检查键是否存在
dd["fruits"].append("banana")
# dd = {"fruits": ["apple", "banana"]}
# Counter(计数器)
from collections import Counter
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
c = Counter(words) # Counter({"apple": 3, "banana": 2, "cherry": 1})
c.most_common(2) # [("apple", 3), ("banana", 2)]
3.4 集合(set)—— 无序、不可变元素、唯一
# 创建
s = {1, 2, 3, 4, 5}
s2 = set([1, 2, 2, 3]) # {1, 2, 3}(自动去重)
empty_set = set() # 注意:{} 是空字典,不是空集合
# 添加/删除
s.add(6)
s.remove(1) # 不存在抛 KeyError
s.discard(99) # 不存在不报错
s.pop() # 随机删除并返回一个元素
s.clear()
# 成员测试(O(1) 时间复杂度,比列表快得多)
3 in s # True
# 集合运算
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # {1, 2, 3, 4, 5, 6} 并集
a & b # {3, 4} 交集
a - b # {1, 2} 差集(在a不在b)
b - a # {5, 6} 差集(在b不在a)
a ^ b # {1, 2, 5, 6} 对称差集(不共有的元素)
# 子集/超集判断
{1, 2} <= {1, 2, 3} # True(子集)
{1, 2} < {1, 2, 3} # True(真子集)
{1, 2, 3} >= {1, 2} # True(超集)
# frozenset(不可变集合,可以作为字典的键)
fs = frozenset([1, 2, 3])
3.5 数据结构选择指南
| 需求 | 选择 | 原因 |
|---|---|---|
| 有序集合,需要修改 | list | 索引访问 O(1),末尾追加 O(1) |
| 不可变序列 | tuple | 更安全,可作字典键,更省内存 |
| 键值映射 | dict | 键查找 O(1) |
| 去重 / 成员测试 | set | 查找 O(1),自动去重 |
| 需要默认值的字典 | defaultdict | 省去 if key not in dict 判断 |
| 需要计数 | Counter | 自带 most_common() 等方法 |
| 需要按插入顺序的字典 | dict(3.7+ 保证) | 不需要 OrderedDict |
| 双端队列(两端高效增删) | collections.deque | 两端操作 O(1),列表头部插入 O(n) |
四、条件语句
# 基本 if-elif-else
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "D"
# 三元表达式(条件表达式)
status = "adult" if age >= 18 else "minor"
# 真值测试规则(以下值为 False)
bool(False) # False
bool(None) # False
bool(0) # False(包括 0, 0.0, 0j)
bool("") # False(空字符串)
bool(b"") # False(空字节串)
bool([]) # False(空列表)
bool(()) # False(空元组)
bool({}) # False(空字典)
bool(set()) # False(空集合)
# 其他所有值都为 True
# 逻辑运算符(短路求值)
x and y # x 为假返回 x,否则返回 y
x or y # x 为真返回 x,否则返回 y
not x # 布尔取反
# 海象运算符在条件中使用(Python 3.8+)
if (n := len(data)) > 10:
print(f"Data is too long ({n} items)")
# 模式匹配 match-case(Python 3.10+)
# 详见下方"模式匹配"章节
五、循环
5.1 for 循环
# 遍历列表
for item in [1, 2, 3]:
print(item)
# 遍历字符串
for char in "hello":
print(char)
# range(start, stop, step)
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 8): # 2, 3, 4, 5, 6, 7
print(i)
for i in range(0, 10, 2): # 0, 2, 4, 6, 8
print(i)
for i in range(10, 0, -1): # 10, 9, 8, ..., 1
print(i)
# enumerate(同时获取索引和值)
for i, item in enumerate(["a", "b", "c"]):
print(f"{i}: {item}") # 0: a, 1: b, 2: c
for i, item in enumerate(["a", "b", "c"], start=1):
print(f"{i}: {item}") # 1: a, 2: b, 3: c
# zip(并行遍历多个序列)
names = ["Alice", "Bob"]
ages = [30, 25]
for name, age in zip(names, ages):
print(f"{name} is {age}")
# 遍历字典
for key in d:
print(key)
for key, value in d.items():
print(f"{key}: {value}")
# 遍历集合
for item in {1, 2, 3}:
print(item)
5.2 while 循环
count = 0
while count < 5:
print(count)
count += 1
# while-else(循环正常结束时执行 else,break 跳出则不执行)
while count < 10:
count += 1
if count == 5:
break
else:
print("循环正常结束") # 不会执行,因为 break 了
5.3 循环控制
# break:跳出当前循环
for i in range(10):
if i == 5:
break
print(i) # 0, 1, 2, 3, 4
# continue:跳过本次迭代
for i in range(5):
if i == 2:
continue
print(i) # 0, 1, 3, 4
# pass:空操作占位符
for i in range(5):
pass # TODO: 稍后实现
# for-else / while-else(循环正常结束时执行 else)
for i in range(10):
if i == 5:
break
else:
print("没有找到") # break 了,不执行
for i in range(10):
if i == 100:
break
else:
print("遍历完成,没有找到") # 正常结束,执行
5.4 推导式(Comprehensions)
# 列表推导式
squares = [x**2 for x in range(10)] # [0, 1, 4, 9, ..., 81]
evens = [x for x in range(20) if x % 2 == 0] # [0, 2, 4, ..., 18]
flat = [x for row in matrix for x in row] # 嵌套展平
# 字典推导式
word_lengths = {word: len(word) for word in ["hi", "hello", "hey"]}
# {"hi": 2, "hello": 5, "hey": 3}
inverted = {v: k for k, v in original_dict.items()} # 反转键值
# 集合推导式
unique_lengths = {len(word) for word in ["hi", "hey", "hello"]}
# {2, 3, 5}
# 生成器表达式(用圆括号,惰性求值,不立即创建列表)
total = sum(x**2 for x in range(1000000)) # 不占用内存
六、函数
6.1 基础定义
def greet(name: str) -> str:
"""向指定的人打招呼。""" # docstring
return f"Hello, {name}!"
result = greet("Alice") # "Hello, Alice!"
6.2 参数类型
# 位置参数
def f(a, b):
return a + b
f(1, 2) # 3
# 默认参数(注意:默认值不要用可变对象!)
def append_to(item, target=[]): # ❌ 危险!默认值只创建一次
target.append(item)
return target
def append_to(item, target=None): # ✅ 正确做法
if target is None:
target = []
target.append(item)
return target
# 关键字参数
def profile(name, age, city="Beijing"):
print(f"{name}, {age}, {city}")
profile("Alice", 30) # 使用默认值
profile("Bob", 25, city="Shanghai") # 关键字传参
# *args:接收任意数量的位置参数(打包为元组)
def sum_all(*args):
return sum(args)
sum_all(1, 2, 3, 4) # 10
# **kwargs:接收任意数量的关键字参数(打包为字典)
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="Beijing")
# 混合使用(顺序:位置参数 → *args → 关键字参数 → **kwargs)
def f(a, b, *args, key1="default", **kwargs):
print(a, b, args, key1, kwargs)
f(1, 2, 3, 4, key1="custom", extra="data")
# 1 2 (3, 4) custom {'extra': 'data'}
# 仅位置参数(Python 3.8+,用 / 标记)
def f(a, b, /, c, d):
pass
f(1, 2, c=3, d=4) # ✅
# f(1, 2, 3, 4) # ✅
# f(a=1, b=2, c=3, d=4) # ❌ a, b 只能按位置传
# 仅关键字参数(用 * 标记)
def f(a, b, *, key1, key2="default"):
pass
f(1, 2, key1=3) # ✅
# f(1, 2, 3) # ❌ key1 必须用关键字传
6.3 返回值
# 返回单个值
def add(a, b):
return a + b
# 返回多个值(实际是返回元组)
def divide(a, b):
return a // b, a % b
quotient, remainder = divide(10, 3) # 3, 1
# 没有 return 或 return 后无值 → 返回 None
def do_nothing():
pass
result = do_nothing() # None
# 提前返回
def find_first_even(nums):
for n in nums:
if n % 2 == 0:
return n
return None # 没找到
6.4 作用域(LEGB 规则)
# L: Local(函数内部)
# E: Enclosing(外层函数)
# G: Global(模块级别)
# B: Built-in(内置名称)
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # "local"
inner()
print(x) # "enclosing"
outer()
print(x) # "global"
# global 声明:在函数内修改全局变量
count = 0
def increment():
global count
count += 1
# nonlocal 声明:在嵌套函数中修改外层函数的变量
def counter():
count = 0
def increment():
nonlocal count
count += 1
return increment
6.5 Lambda 表达式
# 匿名函数(单行表达式)
square = lambda x: x ** 2
square(5) # 25
add = lambda a, b: a + b
add(1, 2) # 3
# 常用作排序键
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
students.sort(key=lambda s: s[1], reverse=True)
# [("Bob", 92), ("Alice", 85), ("Charlie", 78)]
# 配合高阶函数
list(map(lambda x: x*2, [1, 2, 3])) # [2, 4, 6]
list(filter(lambda x: x > 0, [-1, 0, 1])) # [1]
6.6 高阶函数
# map:对每个元素应用函数
list(map(str, [1, 2, 3])) # ["1", "2", "3"]
# filter:过滤元素
list(filter(lambda x: x > 0, [-2, -1, 0, 1, 2])) # [1, 2]
# sorted:自定义排序
sorted(["banana", "apple", "cherry"], key=len)
# ["apple", "banana", "cherry"]
# functools.reduce:累积计算
from functools import reduce
reduce(lambda a, b: a + b, [1, 2, 3, 4]) # 10
# functools.partial:偏函数(固定部分参数)
from functools import partial
double = partial(lambda x, y: x * y, 2)
double(5) # 10
七、面向对象编程
7.1 类定义
class Dog:
"""一只狗的类。""" # 类文档字符串
# 类属性(所有实例共享)
species = "Canis familiaris"
# 初始化方法(构造函数)
def __init__(self, name: str, age: int):
# 实例属性
self.name = name
self.age = age
# 实例方法(第一个参数是 self)
def bark(self) -> str:
return f"{self.name} says Woof!"
# 另一个实例方法
def description(self) -> str:
return f"{self.name} is {self.age} years old"
# 特殊方法(魔术方法)
def __str__(self) -> str:
return f"Dog({self.name}, {self.age})"
def __repr__(self) -> str:
return f"Dog(name={self.name!r}, age={self.age})"
# 创建实例
my_dog = Dog("Rex", 3)
my_dog.bark() # "Rex says Woof!"
print(my_dog) # "Dog(Rex, 3)"(调用 __str__)
7.2 继承
class Animal:
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
raise NotImplementedError("子类必须实现 speak()")
class Cat(Animal):
def __init__(self, name: str, indoor: bool = True):
super().__init__(name) # 调用父类 __init__
self.indoor = indoor
def speak(self) -> str:
return f"{self.name} says Meow!"
class Dog(Animal):
def speak(self) -> str:
return f"{self.name} says Woof!"
# 多态
animals = [Cat("Whiskers"), Dog("Rex")]
for animal in animals:
print(animal.speak())
# 多继承
class Flyable:
def fly(self):
return f"{self.name} is flying"
class FlyingCat(Cat, Flyable):
pass
fc = FlyingCat("Luna")
fc.speak() # "Luna says Meow!"(来自 Cat)
fc.fly() # "Luna is flying"(来自 Flyable)
# MRO(方法解析顺序)
FlyingCat.__mro__ # (FlyingCat, Cat, Animal, Flyable, object)
7.3 类方法、静态方法、属性
class Temperature:
_count = 0 # 类属性(私有约定)
def __init__(self, celsius: float):
self._celsius = celsius
Temperature._count += 1
# @property:将方法变为只读属性
@property
def fahrenheit(self) -> float:
return self._celsius * 9/5 + 32
@property
def celsius(self) -> float:
return self._celsius
# @setter:允许修改属性
@celsius.setter
def celsius(self, value: float):
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
# @classmethod:类方法(第一个参数是 cls)
@classmethod
def from_fahrenheit(cls, f: float) -> "Temperature":
return cls((f - 32) * 5/9)
# @staticmethod:静态方法(不需要 self 或 cls)
@staticmethod
def is_freezing(celsius: float) -> bool:
return celsius <= 0
# 类方法获取实例数
@classmethod
def get_count(cls) -> int:
return cls._count
t = Temperature(100)
t.fahrenheit # 212.0(像属性一样访问,不需要加括号)
t.celsius = 0 # 通过 setter 设置
t.celsius = -300 # ❌ ValueError
t2 = Temperature.from_fahrenheit(32) # 通过类方法创建
Temperature.is_freezing(0) # True(静态方法)
7.4 dataclass(Python 3.7+)
from dataclasses import dataclass, field
@dataclass
class User:
name: str
age: int
email: str = "unknown"
tags: list[str] = field(default_factory=list) # 可变默认值必须用 field
# 自动生成:__init__、__repr__、__eq__、__hash__(如果 frozen)
u1 = User("Alice", 30, "alice@example.com")
u2 = User("Alice", 30, "alice@example.com")
u1 == u2 # True(自动基于字段比较)
print(u1) # User(name='Alice', age=30, email='alice@example.com', tags=[])
# frozen=True:不可变(类似命名元组,但更灵活)
@dataclass(frozen=True)
class Point:
x: float
y: float
p = Point(1.0, 2.0)
# p.x = 3.0 # ❌ FrozenInstanceError
# 可以用作字典的键(因为 frozen + 自动 __hash__)
locations = {Point(0, 0): "origin", Point(1, 1): "diagonal"}
# slots=True(Python 3.10+):减少内存占用
@dataclass(slots=True)
class Sensor:
id: int
value: float
# order=True:自动生成 __lt__、__le__、__gt__、__ge__
@dataclass(order=True)
class Score:
value: float
name: str = field(compare=False) # 不参与比较
scores = [Score(85, "Alice"), Score(92, "Bob"), Score(78, "Charlie")]
sorted(scores) # 按 value 排序
7.5 抽象类
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float:
"""计算面积。"""
pass
@abstractmethod
def perimeter(self) -> float:
"""计算周长。"""
pass
class Circle(Shape):
def __init__(self, radius: float):
self.radius = radius
def area(self) -> float:
return 3.14159 * self.radius ** 2
def perimeter(self) -> float:
return 2 * 3.14159 * self.radius
# shape = Shape() # ❌ TypeError: 不能实例化抽象类
c = Circle(5) # ✅ 实现了所有抽象方法
7.6 常用魔术方法
| 方法 | 触发方式 | 用途 |
|---|---|---|
__init__(self, ...) | MyClass() | 初始化 |
__str__(self) | str(obj) / print(obj) | 用户友好的字符串表示 |
__repr__(self) | repr(obj) / 交互式显示 | 开发者友好的字符串表示 |
__len__(self) | len(obj) | 长度 |
__getitem__(self, key) | obj[key] | 索引/键访问 |
__setitem__(self, key, val) | obj[key] = val | 索引/键赋值 |
__delitem__(self, key) | del obj[key] | 删除元素 |
__contains__(self, item) | item in obj | 成员测试 |
__iter__(self) | for x in obj | 迭代 |
__next__(self) | next(iterator) | 获取下一个元素 |
__eq__(self, other) | obj1 == obj2 | 相等比较 |
__hash__(self) | hash(obj) | 哈希(用于 dict/set 键) |
__lt__, __le__, __gt__, __ge__ | <, <=, >, >= | 大小比较 |
__add__(self, other) | obj1 + obj2 | 加法 |
__enter__ / __exit__ | with obj: | 上下文管理器 |
__call__(self, ...) | obj() | 让实例可调用 |
__bool__(self) | bool(obj) | 布尔值(默认 __len__ 为 0 则 False) |
八、异常处理
8.1 基本语法
try:
result = 10 / 0
except ZeroDivisionError:
print("不能除以零")
except (TypeError, ValueError) as e:
print(f"类型或值错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
else:
print("没有异常时执行") # 可选
finally:
print("无论如何都执行") # 可选,常用于清理资源
8.2 异常层次结构
BaseException
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit
└── Exception ← 通常只捕获这个
├── ArithmeticError
│ ├── ZeroDivisionError
│ ├── OverflowError
│ └── FloatingPointError
├── AttributeError
├── IOError / OSError
│ ├── FileNotFoundError
│ ├── PermissionError
│ └── TimeoutError
├── ImportError
│ └── ModuleNotFoundError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── NameError
│ └── UnboundLocalError
├── TypeError
├── ValueError
│ └── UnicodeDecodeError
└── RuntimeError
├── NotImplementedError
└── RecursionError
⚠️ 永远不要裸
except:,这会连KeyboardInterrupt和SystemExit都捕获。至少写except Exception:。
8.3 自定义异常
class AppError(Exception):
"""应用基础异常。"""
pass
class ValidationError(AppError):
"""数据校验异常。"""
def __init__(self, field: str, message: str):
self.field = field
self.message = message
super().__init__(f"Field '{field}': {message}")
class NotFoundError(AppError):
"""资源未找到异常。"""
pass
# 使用
try:
raise ValidationError("email", "格式不正确")
except ValidationError as e:
print(e.field) # "email"
print(e.message) # "格式不正确"
print(e) # "Field 'email': 格式不正确"
8.4 异常链(Exception Chaining)
try:
result = 10 / 0
except ZeroDivisionError as e:
raise ValueError("计算失败") from e
# 输出会显示原始异常和新的异常,用 "The above exception was the direct cause" 连接
# raise ... from None:隐藏原始异常
try:
result = 10 / 0
except ZeroDivisionError:
raise ValueError("计算失败") from None
8.5 异常组(Python 3.11+)
# 同时处理多个异常
try:
raise ExceptionGroup("多个错误", [
ValueError("值错误"),
TypeError("类型错误"),
])
except* ValueError as eg:
for e in eg.exceptions:
print(f"ValueError: {e}")
except* TypeError as eg:
for e in eg.exceptions:
print(f"TypeError: {e}")
8.6 BaseException.add_note()(Python 3.11+)
try:
1 / 0
except ZeroDivisionError as e:
e.add_note("发生在计算平均值时")
e.add_note(f"输入数据: {data}")
raise
# 异常回溯中会显示附加的 note 信息
九、模块与包
9.1 导入语法
# 导入整个模块
import os
import sys
os.path.join("/home", "user")
# 导入指定内容
from os.path import join, exists
from collections import defaultdict, Counter
# 别名
import numpy as np
from datetime import datetime as dt
from typing import Optional as Opt
# 相对导入(包内部使用)
from . import utils # 同包下的 utils 模块
from .. import config # 上级包的 config 模块
from .utils import helper # 同包下 utils 模块的 helper 函数
# 导入所有(不推荐,会污染命名空间)
from module import *
9.2 包结构
my_package/
├── __init__.py # 标记为包(可以为空)
├── module_a.py
├── module_b.py
└── sub_package/
├── __init__.py
└── module_c.py
9.3 __init__.py 的作用
# my_package/__init__.py
# 控制 from my_package import * 时导出什么
__all__ = ["module_a", "module_b"]
# 也可以在这里做包级别的初始化
from .module_a import SomeClass
# 这样用户可以直接 from my_package import SomeClass
9.4 if __name__ == "__main__" 模式
# my_script.py
def main():
print("Running as script")
if __name__ == "__main__":
main()
# 只有直接运行 python my_script.py 时才执行
# 被 import 时不执行
十、文件操作
10.1 文本文件
# 写入(推荐用 with 自动关闭)
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello\n")
f.write("World\n")
f.writelines(["Line 1\n", "Line 2\n"])
# 读取全部内容
with open("input.txt", "r", encoding="utf-8") as f:
content = f.read()
# 按行读取(推荐,内存友好)
with open("input.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
# 读取所有行到列表
with open("input.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
# 追加模式
with open("log.txt", "a", encoding="utf-8") as f:
f.write("New log entry\n")
10.2 文件模式
| 模式 | 说明 |
|---|---|
"r" | 只读(默认) |
"w" | 写入(覆盖) |
"a" | 追加 |
"x" | 创建(文件已存在则报错) |
"b" | 二进制模式(与上面组合,如 "rb"、"wb") |
"t" | 文本模式(默认,与上面组合,如 "rt") |
"r+" | 读写 |
"w+" | 读写(覆盖) |
10.3 JSON 文件
import json
# 写入 JSON
data = {"name": "Alice", "age": 30, "tags": ["python", "ai"]}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# 读取 JSON
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
# 字符串 ↔ JSON
json_str = json.dumps(data, indent=2) # dict → str
parsed = json.loads(json_str) # str → dict
10.4 CSV 文件
import csv
# 写入
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["name", "age", "city"])
writer.writerow(["Alice", 30, "Beijing"])
writer.writerows([["Bob", 25, "Shanghai"], ["Charlie", 35, "Shenzhen"]])
# 读取
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # 跳过表头
for row in reader:
print(row)
# DictReader / DictWriter(用字典操作)
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], row["age"])
10.5 pathlib(面向对象的路径操作,推荐替代 os.path)
from pathlib import Path
# 创建路径
p = Path("/home/user/documents")
p = Path.home() # 用户主目录
p = Path.cwd() # 当前工作目录
p = Path("data") / "sub" / "file.txt" # 路径拼接(推荐)
# 路径组件
p.name # "file.txt"(文件名)
p.stem # "file"(不含扩展名)
p.suffix # ".txt"(扩展名)
p.parent # Path("data/sub")
p.parts # ("data", "sub", "file.txt")
# 判断
p.exists() # 是否存在
p.is_file() # 是否是文件
p.is_dir() # 是否是目录
p.is_absolute() # 是否是绝对路径
# 文件操作
p.read_text(encoding="utf-8") # 读取文本
p.read_bytes() # 读取字节
p.write_text("hello", encoding="utf-8") # 写入文本
p.write_bytes(b"hello") # 写入字节
# 目录操作
p.mkdir(parents=True, exist_ok=True) # 创建目录
list(p.iterdir()) # 列出目录内容
list(p.glob("*.py")) # 匹配文件
list(p.rglob("*.txt")) # 递归匹配
# 路径转换
p.resolve() # 绝对路径(解析符号链接)
p.absolute() # 绝对路径(不解析符号链接)
p.relative_to(Path("/home")) # 相对路径
十一、类型标注(typing)
11.1 基础标注
# Python 3.9+ 可以直接用小写内置类型
def greet(name: str) -> str:
return f"Hello, {name}"
def process(items: list[int]) -> dict[str, int]:
pass
def get_coords() -> tuple[float, float]:
return (1.0, 2.0)
def get_tags() -> set[str]:
return {"python", "ai"}
11.2 Optional 与 Union
# 可选值(可以是 None)
def find_user(id: int) -> User | None: # Python 3.10+ 语法
pass
# 等价写法
from typing import Optional, Union
def find_user(id: int) -> Optional[User]: # 传统写法
pass
def find_user(id: int) -> Union[User, None]: # 更明确的写法
pass
# 多种类型
def process(value: int | str | float) -> str: # Python 3.10+
pass
def process(value: Union[int, str, float]) -> str: # 传统写法
pass
11.3 高级类型
from typing import (
Literal, # 字面量类型
TypedDict, # 字典结构类型
Callable, # 可调用类型
TypeAlias, # 类型别名
Any, # 任意类型(尽量避免)
Never, # 永不返回(Python 3.11+)
Self, # 当前类类型(Python 3.11+)
TypeGuard, # 类型守卫(Python 3.10+)
Protocol, # 结构化子类型(鸭子类型)
overload, # 函数重载
)
# Literal:限定具体值
def set_mode(mode: Literal["read", "write", "append"]) -> None:
pass
# TypedDict:定义字典结构
class UserInfo(TypedDict):
name: str
age: int
email: str # 必填
class UserInfoOptional(TypedDict, total=False):
name: str
age: int
email: str # 全部可选
# Callable:函数类型
def apply(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
# 类型别名(Python 3.12+ 新语法)
type Vector = list[float]
type Matrix = list[Vector]
type JsonValue = str | int | float | bool | None | list["JsonValue"] | dict[str, "JsonValue"]
# Protocol:结构化子类型(不需要继承)
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
class Circle:
def draw(self) -> None:
print("Drawing circle")
def render(obj: Drawable): # Circle 自动满足 Drawable 协议
obj.draw()
# @overload:函数重载(给类型检查器看的,运行时不生效)
from typing import overload
@overload
def process(x: int) -> int: ...
@overload
def process(x: str) -> str: ...
def process(x: int | str) -> int | str:
if isinstance(x, int):
return x * 2
return x.upper()
11.4 泛型(Python 3.12+ 新语法)
# Python 3.12+ 新语法(PEP 695)
class Stack[T]:
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def first[T](items: list[T]) -> T:
return items[0]
# 带约束的类型参数
def max_val[T: (int, float)](a: T, b: T) -> T:
return a if a > b else b
# 类型别名也可以是泛型(Python 3.12+)
type Pair[T] = tuple[T, T]
type Result[T, E] = tuple[T | None, E | None]
十二、生成器(Generator)
12.1 生成器函数
# 用 yield 定义生成器函数
def count_up(max_val: int):
n = 0
while n < max_val:
yield n
n += 1
# 使用
for num in count_up(5):
print(num) # 0, 1, 2, 3, 4
# 生成器是惰性求值的,不会一次性创建所有值
gen = count_up(1000000) # 几乎不占内存
next(gen) # 0
next(gen) # 1
12.2 yield from(委托生成器)
def flatten(nested_list):
for item in nested_list:
if isinstance(item, list):
yield from flatten(item) # 委托给子生成器
else:
yield item
list(flatten([1, [2, 3], [4, [5, 6]]])) # [1, 2, 3, 4, 5, 6]
12.3 生成器表达式
# 圆括号创建生成器表达式(惰性求值)
squares = (x**2 for x in range(1000000)) # 不占内存
sum(x**2 for x in range(1000000)) # 直接传给函数时不需要额外括号
12.4 send() 与生成器双向通信
def accumulator():
total = 0
while True:
value = yield total # 产出 total,接收外部 send 的值
if value is None:
break
total += value
acc = accumulator()
next(acc) # 启动生成器,运行到第一个 yield,返回 0
acc.send(10) # 发送 10,返回 10
acc.send(20) # 发送 20,返回 30
acc.send(5) # 发送 5,返回 35
acc.send(None) # 结束生成器
十三、装饰器(Decorator)
13.1 基础装饰器
import functools
import time
def timer(func):
"""计算函数执行时间的装饰器。"""
@functools.wraps(func) # 保留原函数的 __name__ 和 __doc__
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} took {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "done"
slow_function() # "slow_function took 1.0012s"
13.2 带参数的装饰器
def retry(max_attempts: int = 3, delay: float = 1.0):
"""失败重试装饰器。"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"Attempt {attempt} failed: {e}, retrying...")
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=5, delay=0.5)
def fetch_data(url: str):
pass
13.3 类装饰器
class CountCalls:
"""记录函数被调用次数的类装饰器。"""
def __init__(self, func):
self.func = func
self.count = 0
functools.update_wrapper(self, func)
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call {self.count} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello() # Call 1 of say_hello / Hello!
say_hello() # Call 2 of say_hello / Hello!
13.4 多个装饰器叠加
# 装饰器从下到上应用(最靠近函数的先应用)
@decorator_a
@decorator_b
@decorator_c
def func():
pass
# 等价于:func = decorator_a(decorator_b(decorator_c(func)))
十四、上下文管理器(Context Manager)
14.1 with 语句
# 文件操作(自动关闭)
with open("file.txt", "r") as f:
content = f.read()
# 多个上下文管理器
with open("in.txt") as fin, open("out.txt", "w") as fout:
fout.write(fin.read())
# Python 3.10+:带括号的上下文管理器(可多行)
with (
open("in.txt") as fin,
open("out.txt", "w") as fout,
):
fout.write(fin.read())
14.2 自定义上下文管理器(类方式)
class DatabaseConnection:
def __init__(self, connection_string: str):
self.connection_string = connection_string
self.connection = None
def __enter__(self):
print("Connecting to database...")
self.connection = f"conn:{self.connection_string}"
return self.connection # 赋值给 as 后面的变量
def __exit__(self, exc_type, exc_val, exc_tb):
print("Closing connection...")
self.connection = None
# 返回 True 会抑制异常,返回 False 或 None 会传播异常
return False
with DatabaseConnection("postgres://localhost/mydb") as conn:
print(f"Using {conn}")
# 退出 with 块时自动调用 __exit__
14.3 自定义上下文管理器(生成器方式)
from contextlib import contextmanager
@contextmanager
def temporary_directory():
"""创建临时目录,退出时自动删除。"""
import tempfile, shutil
tmpdir = tempfile.mkdtemp()
try:
yield tmpdir # yield 的值赋值给 as 后面的变量
finally:
shutil.rmtree(tmpdir) # 无论如何都会清理
with temporary_directory() as tmpdir:
print(f"Working in {tmpdir}")
# 退出 with 块时自动删除临时目录
十五、迭代器协议
# 可迭代对象:实现了 __iter__() 方法
# 迭代器:实现了 __iter__() 和 __next__() 方法
class CountDown:
"""倒计时迭代器。"""
def __init__(self, start: int):
self.current = start
def __iter__(self):
return self # 迭代器返回自身
def __next__(self):
if self.current <= 0:
raise StopIteration
self.current -= 1
return self.current + 1
for num in CountDown(5):
print(num) # 5, 4, 3, 2, 1
# iter() 和 next()
nums = [1, 2, 3]
it = iter(nums) # 获取迭代器
next(it) # 1
next(it) # 2
next(it) # 3
next(it) # ❌ StopIteration
next(it, "done") # "done"(提供默认值不抛异常)
十六、模式匹配(match-case,Python 3.10+)
# 基础匹配
def handle_status(status_code: int) -> str:
match status_code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500 | 502 | 503: # 多个值
return "Server Error"
case _: # 通配符(类似 default)
return "Unknown"
# 解构匹配
def process_command(command: str):
match command.split():
case ["quit"]:
print("Goodbye!")
case ["go", direction]:
print(f"Going {direction}")
case ["go", direction, speed]:
print(f"Going {direction} at {speed}")
case _:
print("Unknown command")
# 匹配字典
def handle_event(event: dict):
match event:
case {"type": "click", "x": x, "y": y}:
print(f"Click at ({x}, {y})")
case {"type": "keypress", "key": key}:
print(f"Key pressed: {key}")
case {"type": "resize", "width": w, "height": h} if w > 1000:
print(f"Large resize: {w}x{h}") # 守卫条件
case _:
print("Unknown event")
# 匹配类实例
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def describe_point(point: Point):
match point:
case Point(0, 0):
return "Origin"
case Point(0, y):
return f"On Y-axis at {y}"
case Point(x, 0):
return f"On X-axis at {x}"
case Point(x, y) if x == y:
return f"On diagonal at ({x}, {y})"
case Point(x, y):
return f"Point at ({x}, {y})"
# 捕获子模式(Python 3.10+)
match response:
case {"status": 200, "body": body} as full_response:
print(f"Success: {body}")
print(f"Full: {full_response}")
十七、正则表达式(re 模块)
import re
text = "Contact us at support@example.com or sales@test.org"
# 搜索
match = re.search(r'[\w.]+@[\w.]+', text)
if match:
print(match.group()) # "support@example.com"
print(match.start()) # 起始位置
print(match.end()) # 结束位置
print(match.span()) # (起始, 结束)
# 查找所有
emails = re.findall(r'[\w.]+@[\w.]+', text)
# ["support@example.com", "sales@test.org"]
# 替换
result = re.sub(r'\d+', 'NUM', "Order 123 has 45 items")
# "Order NUM has NUM items"
# 分割
parts = re.split(r'[;,\s]+', "a, b; c d")
# ["a", "b", "c", "d"]
# 编译正则(重复使用时性能更好)
email_pattern = re.compile(r'[\w.]+@[\w.]+.[\w]+')
matches = email_pattern.findall(text)
# 命名分组
pattern = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})')
m = pattern.match("2024-01-15")
m.group("year") # "2024"
m.group("month") # "01"
m.groupdict() # {"year": "2024", "month": "01", "day": "15"}
# 常用标志
re.IGNORECASE # 忽略大小写
re.MULTILINE # ^ 和 $ 匹配每行
re.DOTALL # . 匹配换行符
re.VERBOSE # 允许注释和空白
# 常用模式速查
# \d 数字 \D 非数字
# \w 字母数字 \W 非字母数字
# \s 空白 \S 非空白
# . 任意字符(除换行)
# ^ 行首 $ 行尾
# * 0次或多次 + 1次或多次
# ? 0次或1次 {n} 恰好n次
# {n,m} n到m次 (?:...) 非捕获组
十八、日期与时间
from datetime import datetime, date, time, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# 当前时间
now = datetime.now() # 本地时间
utc_now = datetime.now(ZoneInfo("UTC")) # UTC 时间
today = date.today() # 今天日期
# 创建
dt = datetime(2024, 1, 15, 10, 30, 0)
d = date(2024, 1, 15)
t = time(10, 30, 0)
# 格式化
dt.strftime("%Y-%m-%d %H:%M:%S") # "2024-01-15 10:30:00"
dt.strftime("%Y年%m月%d日 %H:%M") # "2024年01月15日 10:30"
# 解析
datetime.strptime("2024-01-15 10:30:00", "%Y-%m-%d %H:%M:%S")
# 时间差
delta = timedelta(days=7, hours=3)
future = now + delta
past = now - timedelta(weeks=2)
diff = dt1 - dt2 # 返回 timedelta
# 时区
beijing_time = datetime.now(ZoneInfo("Asia/Shanghai"))
tokyo_time = beijing_time.astimezone(ZoneInfo("Asia/Tokyo"))
# 时间戳
timestamp = datetime.now().timestamp() # float
dt = datetime.fromtimestamp(1705276800) # 时间戳 → datetime
dt = datetime.fromtimestamp(1705276800, tz=ZoneInfo("UTC"))
十九、常用标准库速查
| 模块 | 用途 | 常用功能 |
|---|---|---|
os | 操作系统交互 | os.environ、os.path(推荐用 pathlib 替代) |
sys | 解释器相关 | sys.argv(命令行参数)、sys.path、sys.exit() |
json | JSON 编解码 | json.dumps()、json.loads()、json.dump()、json.load() |
re | 正则表达式 | re.search()、re.findall()、re.sub() |
datetime | 日期时间 | datetime.now()、timedelta、strftime/strptime |
collections | 高级数据结构 | defaultdict、Counter、deque、OrderedDict、namedtuple |
itertools | 迭代器工具 | chain、product、combinations、permutations、groupby |
functools | 函数工具 | lru_cache、partial、reduce、wraps |
pathlib | 路径操作 | Path(推荐替代 os.path) |
typing | 类型标注 | Optional、Union、Literal、TypedDict、Protocol |
dataclasses | 数据类 | @dataclass |
enum | 枚举 | Enum、IntEnum、Flag |
logging | 日志 | logging.getLogger()、basicConfig() |
unittest | 单元测试 | TestCase、assertEqual |
math | 数学函数 | ceil、floor、sqrt、log、gcd |
random | 随机数 | random()、randint()、choice()、shuffle() |
hashlib | 哈希 | md5()、sha256() |
uuid | UUID | uuid4()(随机)、uuid1()(基于时间) |
copy | 复制 | copy.copy()(浅拷贝)、copy.deepcopy()(深拷贝) |
abc | 抽象基类 | ABC、abstractmethod |
contextlib | 上下文管理器 | contextmanager、suppress、redirect_stdout |
textwrap | 文本包装 | dedent()、wrap()、fill() |
二十、异步编程基础(asyncio)
import asyncio
# 定义协程
async def fetch_data(url: str) -> dict:
await asyncio.sleep(1) # 模拟网络请求
return {"url": url, "status": 200}
# 运行协程(程序入口)
async def main():
# 等待单个协程
result = await fetch_data("https://api.example.com")
# 并发执行多个协程
results = await asyncio.gather(
fetch_data("https://api1.example.com"),
fetch_data("https://api2.example.com"),
fetch_data("https://api3.example.com"),
)
# 创建后台任务(不立即等待)
task = asyncio.create_task(fetch_data("https://api.example.com"))
# ... 做其他事 ...
result = await task # 需要时再等待
# 带超时的等待
try:
result = await asyncio.wait_for(fetch_data("..."), timeout=5.0)
except asyncio.TimeoutError:
print("请求超时")
# 限制并发数
semaphore = asyncio.Semaphore(3) # 最多3个并发
async def limited_fetch(url):
async with semaphore:
return await fetch_data(url)
await asyncio.gather(*[limited_fetch(f"url_{i}") for i in range(10)])
# 启动
asyncio.run(main())
以上就是 Python 基础语法的完整汇总。覆盖了从变量、数据类型到异步编程的所有核心知识点,并标注了各版本引入的新语法。