Contents

Python_Note5

Python 笔记补充内容

本文件补充了前四个笔记中缺失的重要知识点。


一、类型注解(Type Hints)

Python 3.5+ 引入了类型注解,可以在函数定义时指定参数和返回值的类型,提高代码可读性和 IDE 支持。

基本类型注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def greet(name: str) -> str:
    return f"Hello, {name}"

def add(a: int, b: int) -> int:
    return a + b

# 变量类型注解
count: int = 0
name: str = "Alice"
scores: list[float] = [85.5, 90.0, 78.5]

复杂类型注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from typing import List, Dict, Tuple, Optional, Union, Any

# 列表、字典、元组类型
def process_items(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

# 可选类型(可能为 None)
def find_user(id: int) -> Optional[str]:
    # 可能返回字符串,也可能返回 None
    return None

# 联合类型(多种可能)
def parse_value(value: Union[int, str]) -> float:
    return float(value)

# 任意类型
def handle_any(data: Any) -> None:
    print(data)

使用 TypeVar 定义泛型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from typing import TypeVar, Generic

T = TypeVar('T')

class Container(Generic[T]):
    def __init__(self, value: T):
        self.value = value

    def get(self) -> T:
        return self.value

二、上下文管理器(Context Manager)

使用 with 语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 文件操作(推荐方式)
with open('file.txt', 'r') as f:
    content = f.read()
# 文件会自动关闭,无需手动 f.close()

# 自定义上下文管理器 - 使用类
class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()
        # 返回 True 会抑制异常,返回 False 会传播异常
        return False

with FileManager('file.txt', 'r') as f:
    content = f.read()

使用 contextlib 创建上下文管理器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from contextlib import contextmanager

@contextmanager
def my_context():
    # __enter__ 部分
    print("进入上下文")
    yield "资源"
    # __exit__ 部分
    print("退出上下文")

with my_context() as resource:
    print(f"使用 {resource}")

三、生成器(Generator)

生成器是一种特殊的迭代器,使用 yield 语句生成值,节省内存。

生成器函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

# 使用生成器
for num in count_up_to(5):
    print(num)  # 1, 2, 3, 4, 5

# 生成器表达式(类似列表推导式)
squares = (x**2 for x in range(10))
# 注意:生成器表达式用圆括号,列表推导式用方括号

yield from 语法

1
2
3
4
5
6
7
8
9
def chain_generators(*iterables):
    for iterable in iterables:
        yield from iterable

# 或者简化写法
def chain_generators_v2(*iterables):
    for iterable in iterables:
        for item in iterable:
            yield item

无限生成器

1
2
3
4
5
6
7
8
9
def infinite_counter():
    count = 0
    while True:
        yield count
        count += 1

# 使用 itertools.islice 截取
from itertools import islice
first_10 = list(islice(infinite_counter(), 10))

四、itertools 常用函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import itertools

# count - 无限计数器
for i in itertools.count(start=10, step=2):
    if i > 20:
        break
    print(i)  # 10, 12, 14, 16, 18, 20

# cycle - 无限循环迭代
colors = itertools.cycle(['red', 'green', 'blue'])

# repeat - 重复元素
for item in itertools.repeat(10, 3):
    print(item)  # 10, 10, 10

# chain - 连接多个迭代器
list1 = [1, 2, 3]
list2 = ['a', 'b']
combined = itertools.chain(list1, list2)

# islice - 切片迭代器
first_5 = itertools.islice(range(100), 5)

# zip_longest - 不限长度的 zip
result = itertools.zip_longest([1, 2], ['a', 'b', 'c'], fillvalue=None)
# [(1, 'a'), (2, 'b'), (None, 'c')]

# permutations - 排列
perms = itertools.permutations([1, 2, 3], 2)
# [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]

# combinations - 组合
combs = itertools.combinations([1, 2, 3, 4], 2)
# [(1,2), (1,3), (1,4), (2,3), (2,4), (3,4)]

# product - 笛卡尔积
prod = itertools.product([1, 2], ['a', 'b'])
# [(1,'a'), (1,'b'), (2,'a'), (2,'b')]

五、functools 常用函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import functools

# partial - 固定部分参数
def power(base, exponent):
    return base ** exponent

square = functools.partial(power, exponent=2)
cube = functools.partial(power, exponent=3)
print(square(5))  # 25

# lru_cache - 缓存装饰器(记忆化)
@functools.lru_cache(maxsize=128)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# reduce - 累积计算
result = functools.reduce(lambda x, y: x + y, [1, 2, 3, 4])
# 10

# wraps - 保持原函数信息
def my_decorator(func):
    @functools.wraps(func)  # 保持 func 的 __name__, __doc__ 等属性
    def wrapper(*args, **kwargs):
        print("Before call")
        return func(*args, **kwargs)
    return wrapper

六、collections 常用容器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from collections import Counter, defaultdict, OrderedDict, deque, namedtuple

# Counter - 计数器
text = "hello world"
counter = Counter(text)
print(counter)  # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
print(counter.most_common(2))  # [('l', 3), ('o', 2)]

# defaultdict - 带默认值的字典
dd = defaultdict(list)  # 缺失键默认返回空列表
dd['fruits'].append('apple')  # 无需初始化

dd_int = defaultdict(int)  # 缺失键默认返回 0
dd_int['count'] += 1

# OrderedDict - 有序字典(Python 3.7+ 普通字典已有序)
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
od.move_to_end('a')  # 将 'a' 移到末尾

# deque - 双端队列
dq = deque([1, 2, 3])
dq.append(4)       # 右端添加
dq.appendleft(0)   # 左端添加
dq.pop()           # 右端弹出 -> 4
dq.popleft()       # 左端弹出 -> 0

# namedtuple - 命名元组
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y)  # 3, 4

七、数据类(dataclass)

Python 3.7+ 引入了 dataclass,简化类的定义。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from dataclasses import dataclass, field

@dataclass
class Person:
    name: str
    age: int
    email: str = ""  # 默认值

@dataclass
class Student(Person):
    grade: int
    courses: list = field(default_factory=list)  # 可变默认值使用 field

# 自动生成 __init__, __repr__, __eq__ 等方法
p1 = Person("Alice", 25)
p2 = Person("Alice", 25)
print(p1 == p2)  # True(自动实现了 __eq__)

# 还可以设置其他参数
@dataclass(order=True)  # 自动实现比较方法
class OrderedItem:
    price: int
    name: str = field(compare=False)  # name 不参与比较

八、枚举类(Enum)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from enum import Enum, auto

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

# 使用 auto() 自动分配值
class Status(Enum):
    PENDING = auto()
    APPROVED = auto()
    REJECTED = auto()

# 访问枚举
print(Color.RED)        # Color.RED
print(Color.RED.name)   # 'RED'
print(Color.RED.value)  # 1

# 枚举比较
print(Color.RED == Color.RED)   # True
print(Color.RED == 1)           # False(需用 .value)

# 遍历枚举
for color in Color:
    print(color)

九、asyncio 异步编程基础

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import asyncio

# 定义异步函数
async def fetch_data(url):
    print(f"开始获取 {url}")
    await asyncio.sleep(1)  # 模拟 IO 操作
    print(f"完成获取 {url}")
    return f"数据来自 {url}"

# 运行异步函数
async def main():
    result = await fetch_data("https://example.com")
    print(result)

# 执行
asyncio.run(main())

# 并发执行多个任务
async def main_concurrent():
    tasks = [
        fetch_data("url1"),
        fetch_data("url2"),
        fetch_data("url3"),
    ]
    results = await asyncio.gather(*tasks)
    print(results)

asyncio.run(main_concurrent())

十、pathlib 进阶用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pathlib import Path

# 创建路径对象
p = Path('/home/user/documents')
p = Path.home() / 'documents' / 'file.txt'

# 路径属性
print(p.name)      # 'file.txt'
print(p.stem)      # 'file'(不含扩展名)
print(p.suffix)    # '.txt'
print(p.parent)    # Path('/home/user/documents')
print(p.exists())  # 是否存在
print(p.is_file()) # 是否是文件
print(p.is_dir())  # 是否是目录

# 路径操作
p.mkdir(parents=True, exist_ok=True)  # 创建目录
p.touch()                             # 创建文件
p.rename(p.with_suffix('.md'))        # 重命名

# 遍历目录
for file in Path('.').glob('*.py'):
    print(file)

for file in Path('.').rglob('*.py'):   # 递归搜索
    print(file)

# 读写文件
content = p.read_text()
p.write_text("新内容")

十一、Python 版本差异速查

Python 2 vs Python 3 主要差异

特性 Python 2 Python 3
print print "hello" print("hello")
整数除法 5/2 = 2 5/2 = 2.5
字符串 默认 ASCII 默认 Unicode
range 返回列表 返回迭代器
input 返回表达式结果 返回字符串
类定义 class A: 是旧式类 class A: 是新式类

Python 3 新特性时间线

  • 3.5: 类型注解、async/await 语法、math.inf
  • 3.6: f-string、变量注解、asyncio 改进
  • 3.7: dataclass、字典有序(官方保证)、asyncio.run()
  • 3.8: 海象运算符 :=、位置参数 /
  • 3.9: 字典合并 |、泛型类型注解 list[int]
  • 3.10: match-case 语句、结构化模式匹配
  • 3.11: 更快启动速度、异常组 ExceptionGroup
  • 3.12: 类型参数语法 def f[T](x: T): ...

十二、常用内置函数速查

函数 说明 示例
len() 返回长度 len([1,2,3]) → 3
range() 生成数字序列 range(5) → 0,1,2,3,4
enumerate() 带索引遍历 enumerate(['a','b']) → (0,‘a’), (1,‘b’)
zip() 并行迭代 zip([1,2], ['a','b']) → (1,‘a’), (2,‘b’)
map() 应用函数 map(str, [1,2,3]) → ‘1’,‘2’,‘3’
filter() 过滤元素 filter(lambda x:x>0, [-1,1]) → 1
sorted() 排序 sorted([3,1,2]) → [1,2,3]
reversed() 反转 reversed([1,2,3]) → 3,2,1
sum() 求和 sum([1,2,3]) → 6
max() / min() 最大/最小 max([1,5,3]) → 5
any() / all() 逻辑判断 any([False, True]) → True
abs() 绝对值 abs(-5) → 5
round() 四舍五入 round(3.5) → 4
isinstance() 类型检查 isinstance(5, int) → True
type() 返回类型 type(5) → int
dir() 返回属性列表 dir(str)
help() 帮助信息 help(print)

十三、字符串格式化对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
name = "Alice"
age = 25

# 1. % 格式化(旧式)
print("Name: %s, Age: %d" % (name, age))

# 2. str.format()(Python 2.6+)
print("Name: {}, Age: {}".format(name, age))
print("Name: {n}, Age: {a}".format(n=name, a=age))
print("Age: {age:.2f}".format(age=3.14159))  # 3.14

# 3. f-string(Python 3.6+,推荐)
print(f"Name: {name}, Age: {age}")
print(f"Age: {age:.2f}")  # 25.00
print(f"{name.upper()}")  # ALICE(可调用方法)
print(f"Result: {2**10}")  # 1024(可计算表达式)

# f-string 调试模式(Python 3.8+)
print(f"{name=}, {age=}")  # name='Alice', age=25

十四、常用魔法方法速查

方法 说明 示例用途
__init__ 初始化 构造函数
__str__ 字符串表示 print(obj)
__repr__ 详细字符串表示 repr(obj)
__len__ 长度 len(obj)
__getitem__ 获取元素 obj[key]
__setitem__ 设置元素 obj[key] = value
__delitem__ 删除元素 del obj[key]
__iter__ 迭代 for x in obj
__next__ 下一个元素 迭代器
__call__ 调用 obj()
__eq__ 等于比较 obj1 == obj2
__lt__ / __gt__ 比较 obj1 < obj2
__add__ 加法 obj1 + obj2
__enter__ / __exit__ 上下文管理 with obj
__slots__ 限制属性 优化内存

十五、常见陷阱与注意事项

1. 可变默认参数陷阱

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 错误写法
def add_item(item, items=[]):
    items.append(item)
    return items

# 正确写法
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

2. 列表推导式中的闭包陷阱

1
2
3
4
5
6
7
# 错误:所有 lambda 都引用同一个 i
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])  # [2, 2, 2]

# 正确:捕获当前 i 的值
funcs = [lambda i=i: i for i in range(3)]
print([f() for f in funcs])  # [0, 1, 2]

3. 浮点数精度问题

1
2
3
4
5
6
# 问题
0.1 + 0.2  # 0.30000000000000004

# 解决方案:使用 decimal
from decimal import Decimal
Decimal('0.1') + Decimal('0.2')  # Decimal('0.3')

4. 深拷贝 vs 浅拷贝

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import copy

original = [[1, 2], [3, 4]]

# 浅拷贝:只拷贝一层
shallow = copy.copy(original)
shallow[0][0] = 5  # 原始列表也会改变!

# 深拷贝:完全独立
deep = copy.deepcopy(original)
deep[0][0] = 5     # 原始列表不变