Python 高级语法
目录
- 列表推导式进阶
- 生成器表达式
- 字典推导式和集合推导式
- 解包操作
- 条件表达式
- walrus 运算符
- match-case 模式匹配
- 类型提示进阶
- 数据类
- 枚举类型
- 描述符
- 元类
- 协程和异步编程
- 综合实战
列表推导式进阶
基本回顾
# 基本列表推导式
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
嵌套列表推导式
# 二维列表展平
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
flattened = [num for row in matrix for num in row]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 等价于
flattened = []
for row in matrix:
for num in row:
flattened.append(num)
复杂条件
# 多个条件
numbers = [x for x in range(50) if x % 2 == 0 if x % 3 == 0]
print(numbers) # [0, 6, 12, 18, 24, 30, 36, 42, 48]
# if-else 在推导式中
result = ["偶数" if x % 2 == 0 else "奇数" for x in range(10)]
print(result)
# ['偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数']
# 过滤和处理
words = ["hello", "world", "python", "ai", "openai"]
filtered = [word.upper() for word in words if len(word) > 3]
print(filtered) # ['HELLO', 'WORLD', 'PYTHON', 'OPENAI']
嵌套循环的推导式
# 生成坐标点
coordinates = [(x, y) for x in range(3) for y in range(3)]
print(coordinates)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# 乘法表
multiplication_table = [
[i * j for j in range(1, 10)]
for i in range(1, 10)
]
for row in multiplication_table:
print(row)
性能对比
import time
# 列表推导式 vs 传统循环
n = 1000000
# 方法1:列表推导式
start = time.time()
squares1 = [x**2 for x in range(n)]
time1 = time.time() - start
# 方法2:传统循环
start = time.time()
squares2 = []
for x in range(n):
squares2.append(x**2)
time2 = time.time() - start
print(f"列表推导式: {time1:.4f}秒")
print(f"传统循环: {time2:.4f}秒")
print(f"提升: {(time2-time1)/time2*100:.1f}%")
# 列表推导式通常快 20-50%
生成器表达式
基本语法
# 生成器表达式(使用圆括号)
gen = (x**2 for x in range(10))
print(type(gen)) # <class 'generator'>
# 惰性求值
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 4
# 遍历
for value in gen:
print(value, end=" ") # 9 16 25 36 49 64 81
生成器 vs 列表
import sys
# 内存占用对比
n = 1000000
# 列表:立即创建所有元素
my_list = [x**2 for x in range(n)]
print(f"列表大小: {sys.getsizeof(my_list)} bytes") # ~8MB
# 生成器:惰性求值
my_gen = (x**2 for x in range(n))
print(f"生成器大小: {sys.getsizeof(my_gen)} bytes") # ~200 bytes
# 生成器只能遍历一次
gen = (x for x in range(5))
print(list(gen)) # [0, 1, 2, 3, 4]
print(list(gen)) # [](已耗尽)
生成器函数
def fibonacci():
"""斐波那契数列生成器"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 使用
fib = fibonacci()
for _ in range(10):
print(next(fib), end=" ") # 0 1 1 2 3 5 8 13 21 34
生成器管道
def read_lines(filename):
"""读取文件行"""
with open(filename, 'r') as f:
for line in f:
yield line.strip()
def filter_empty(lines):
"""过滤空行"""
for line in lines:
if line:
yield line
def uppercase(lines):
"""转换为大写"""
for line in lines:
yield line.upper()
# 构建处理管道
lines = read_lines("data.txt")
filtered = filter_empty(lines)
uppercased = uppercase(filtered)
for line in uppercased:
print(line)
# 或者使用生成器表达式
lines = (line.strip() for line in open("data.txt"))
filtered = (line for line in lines if line)
uppercased = (line.upper() for line in filtered)
send() 和协程
def accumulator():
"""累加器协程"""
total = 0
while True:
value = yield total
if value is not None:
total += value
# 使用
acc = accumulator()
next(acc) # 启动协程,输出 0
print(acc.send(10)) # 10
print(acc.send(20)) # 30
print(acc.send(30)) # 60
字典推导式和集合推导式
字典推导式
# 基本字典推导式
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["Alice", 25, "Beijing"]
person = {k: v for k, v in zip(keys, values)}
print(person) # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}
# 带条件的字典推导式
original = {"a": 1, "b": 2, "c": 3, "d": 4}
filtered = {k: v for k, v in original.items() if v > 2}
print(filtered) # {'c': 3, 'd': 4}
# 键值转换
inverted = {v: k for k, v in original.items()}
print(inverted) # {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
# 统计字符出现次数
text = "hello world"
char_count = {char: text.count(char) for char in set(text) if char != ' '}
print(char_count) # {'h': 1, 'e': 1, 'l': 3, 'o': 2, 'w': 1, 'r': 1, 'd': 1}
集合推导式
# 基本集合推导式
squares = {x**2 for x in range(-5, 6)}
print(squares) # {0, 1, 4, 9, 16, 25}(自动去重)
# 提取唯一字符
text = "programming"
unique_chars = {char for char in text if char.isalpha()}
print(unique_chars) # {'p', 'r', 'o', 'g', 'a', 'm', 'i', 'n'}
# 带条件的集合推导式
numbers = {x for x in range(50) if x % 3 == 0 or x % 5 == 0}
print(numbers)
实际应用
# 单词频率统计
text = "the quick brown fox jumps over the lazy dog the fox"
words = text.split()
# 使用字典推导式
word_freq = {word: words.count(word) for word in set(words)}
print(word_freq)
# {'the': 3, 'quick': 1, 'brown': 1, 'fox': 2, ...}
# 使用 collections.Counter(更高效)
from collections import Counter
word_freq = Counter(words)
print(word_freq.most_common(3))
# [('the', 3), ('fox', 2), ('quick', 1)]
解包操作
基本解包
# 列表解包
numbers = [1, 2, 3]
a, b, c = numbers
print(a, b, c) # 1 2 3
# 元组解包
point = (10, 20)
x, y = point
print(x, y) # 10 20
# 字符串解包
chars = list("abc")
a, b, c = chars
print(a, b, c) # a b c
扩展解包(* 运算符)
# 收集多余元素
numbers = [1, 2, 3, 4, 5]
first, *middle, last = numbers
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
# 只取前几个
first, second, *rest = numbers
print(first) # 1
print(second) # 2
print(rest) # [3, 4, 5]
# 只取最后一个
*head, last = numbers
print(head) # [1, 2, 3, 4]
print(last) # 5
嵌套解包
# 嵌套结构解包
data = [
("Alice", [90, 85, 92]),
("Bob", [78, 82, 88])
]
for name, (math, english, science) in data:
avg = (math + english + science) / 3
print(f"{name}: 平均分 {avg:.1f}")
# Alice: 平均分 89.0
# Bob: 平均分 82.7
字典解包
# Python 3.5+ 支持字典解包
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
# 合并字典
merged = {**dict1, **dict2}
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 覆盖重复键
dict3 = {"a": 10, "e": 5}
merged2 = {**dict1, **dict3}
print(merged2) # {'a': 10, 'b': 2, 'e': 5}(a 被覆盖)
# Python 3.9+ 使用 | 运算符
merged3 = dict1 | dict2
print(merged3) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
函数参数解包
def greet(name, age, city):
print(f"{name}, {age}岁, 来自{city}")
# 列表/元组解包为位置参数
args = ["张三", 25, "北京"]
greet(*args)
# 字典解包为关键字参数
kwargs = {"name": "李四", "age": 30, "city": "上海"}
greet(**kwargs)
# 混合使用
def func(a, b, c, d):
return a + b + c + d
args = [1, 2]
kwargs = {"c": 3, "d": 4}
result = func(*args, **kwargs)
print(result) # 10
条件表达式
三元运算符
# 基本语法
x = 10
result = "正数" if x > 0 else "非正数"
print(result) # 正数
# 等价于
if x > 0:
result = "正数"
else:
result = "非正数"
嵌套条件表达式
# 多层条件
age = 25
status = "儿童" if age < 12 else "青少年" if age < 18 else "成人"
print(status) # 成人
# 建议:复杂逻辑使用 if-elif-else
if age < 12:
status = "儿童"
elif age < 18:
status = "青少年"
else:
status = "成人"
实际应用
# 默认值
name = user_input if user_input else "匿名用户"
# 最小值/最大值
min_val = a if a < b else b
max_val = a if a > b else b
# 安全访问
value = my_dict.get(key) if key in my_dict else default_value
# 列表中的条件表达式
numbers = [-5, -3, 0, 2, 4, -1]
signs = ["负数" if n < 0 else "零" if n == 0 else "正数" for n in numbers]
print(signs)
# ['负数', '负数', '零', '正数', '正数', '负数']
walrus 运算符
Python 3.8+ 引入的海象运算符 :=,可以在表达式中赋值。
基本用法
# 传统方式
n = len("hello")
if n > 3:
print(f"长度 {n} 大于 3")
# 使用海象运算符
if (n := len("hello")) > 3:
print(f"长度 {n} 大于 3")
while 循环中的应用
# 传统方式
line = input("输入: ")
while line != "quit":
print(f"你输入了: {line}")
line = input("输入: ")
# 使用海象运算符
while (line := input("输入: ")) != "quit":
print(f"你输入了: {line}")
列表推导式中的应用
# 避免重复计算
import re
texts = ["abc123", "def456", "ghi789", "no match"]
# 传统方式(需要两次匹配)
matches = [m.group() for text in texts
for m in [re.search(r'\d+', text)]
if m]
# 使用海象运算符(更清晰)
matches = [match.group()
for text in texts
if (match := re.search(r'\d+', text))]
print(matches) # ['123', '456', '789']
函数调用优化
# 避免重复调用昂贵函数
def expensive_computation(x):
import time
time.sleep(0.1) # 模拟耗时操作
return x ** 2
# 传统方式
results = []
for x in range(5):
result = expensive_computation(x)
if result > 10:
results.append(result)
# 使用海象运算符
results = [result
for x in range(5)
if (result := expensive_computation(x)) > 10]
match-case 模式匹配
Python 3.10+ 引入的结构化模式匹配。
基本语法
def http_status(status_code):
match status_code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500:
return "Internal Server Error"
case _:
return "Unknown Status"
print(http_status(200)) # OK
print(http_status(404)) # Not Found
print(http_status(999)) # Unknown Status
匹配多个值
def get_day_type(day):
match day:
case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
return "工作日"
case "Saturday" | "Sunday":
return "周末"
case _:
return "无效日期"
print(get_day_type("Monday")) # 工作日
print(get_day_type("Saturday")) # 周末
匹配数据结构
# 匹配列表
def process_command(command):
match command:
case ["quit"]:
return "退出程序"
case ["help"]:
return "显示帮助"
case ["load", filename]:
return f"加载文件: {filename}"
case ["save", filename]:
return f"保存文件: {filename}"
case _:
return "未知命令"
print(process_command(["quit"])) # 退出程序
print(process_command(["load", "data.txt"])) # 加载文件: data.txt
匹配字典
def process_event(event):
match event:
case {"type": "click", "x": x, "y": y}:
return f"点击事件: ({x}, {y})"
case {"type": "keypress", "key": key}:
return f"按键事件: {key}"
case {"type": "resize", "width": w, "height": h}:
return f"窗口调整: {w}x{h}"
case _:
return "未知事件"
event1 = {"type": "click", "x": 100, "y": 200}
event2 = {"type": "keypress", "key": "Enter"}
print(process_event(event1)) # 点击事件: (100, 200)
print(process_event(event2)) # 按键事件: Enter
守卫条件
def classify_number(n):
match n:
case n if n > 0:
return "正数"
case n if n < 0:
return "负数"
case 0:
return "零"
print(classify_number(10)) # 正数
print(classify_number(-5)) # 负数
print(classify_number(0)) # 零
匹配对象
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def describe_point(point):
match point:
case Point(x=0, y=0):
return "原点"
case Point(x=0, y=y):
return f"Y轴上的点 (0, {y})"
case Point(x=x, y=0):
return f"X轴上的点 ({x}, 0)"
case Point(x=x, y=y):
return f"普通点 ({x}, {y})"
print(describe_point(Point(0, 0))) # 原点
print(describe_point(Point(0, 5))) # Y轴上的点 (0, 5)
print(describe_point(Point(3, 4))) # 普通点 (3, 4)
类型提示进阶
基本类型提示
from typing import List, Dict, Tuple, Optional, Union
def greet(name: str) -> str:
return f"Hello, {name}"
def add(a: int, b: int) -> int:
return a + b
def get_user(user_id: int) -> Optional[Dict[str, str]]:
"""可能返回 None"""
if user_id > 0:
return {"name": "Alice", "email": "alice@example.com"}
return None
联合类型
from typing import Union
# Python 3.10+ 可以使用 | 符号
def process(value: int | str) -> str:
if isinstance(value, int):
return f"数字: {value}"
return f"字符串: {value}"
# 旧版本写法
def process_old(value: Union[int, str]) -> str:
pass
泛型类型
from typing import TypeVar, Generic, List
T = TypeVar('T')
def first_element(items: List[T]) -> T:
return items[0]
# 使用
numbers: List[int] = [1, 2, 3]
first: int = first_element(numbers)
strings: List[str] = ["a", "b", "c"]
first_str: str = first_element(strings)
自定义泛型类
from typing import Generic, TypeVar, Optional
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self):
self._items: List[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> Optional[T]:
if self._items:
return self._items.pop()
return None
def peek(self) -> Optional[T]:
if self._items:
return self._items[-1]
return None
# 使用
int_stack: Stack[int] = Stack()
int_stack.push(1)
int_stack.push(2)
print(int_stack.pop()) # 2
str_stack: Stack[str] = Stack()
str_stack.push("hello")
Callable 类型
from typing import Callable
def apply_operation(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
def add(a: int, b: int) -> int:
return a + b
def multiply(a: int, b: int) -> int:
return a * b
print(apply_operation(add, 5, 3)) # 8
print(apply_operation(multiply, 5, 3)) # 15
Protocol(结构子类型)
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None:
...
class Circle:
def draw(self) -> None:
print("绘制圆形")
class Rectangle:
def draw(self) -> None:
print("绘制矩形")
def render(shape: Drawable) -> None:
shape.draw()
render(Circle()) # 绘制圆形
render(Rectangle()) # 绘制矩形
运行时类型检查
from typing import get_type_hints
import inspect
def add(a: int, b: int) -> int:
return a + b
# 获取类型提示
hints = get_type_hints(add)
print(hints) # {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}
# 使用 pydantic 进行验证
from pydantic import validate_arguments
@validate_arguments
def create_user(name: str, age: int) -> dict:
return {"name": name, "age": age}
user = create_user("Alice", 25) # ✓
# create_user("Bob", "twenty") # ✗ ValidationError
数据类
Python 3.7+ 引入的 dataclasses 模块。
基本用法
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
email: str = ""
# 自动生成 __init__, __repr__, __eq__ 等方法
person = Person("张三", 25, "zhang@example.com")
print(person) # Person(name='张三', age=25, email='zhang@example.com')
person2 = Person("张三", 25, "zhang@example.com")
print(person == person2) # True
字段配置
from dataclasses import dataclass, field
from typing import List
@dataclass
class Student:
name: str
age: int
grades: List[float] = field(default_factory=list)
student_id: str = field(init=False) # 不在 __init__ 中
def __post_init__(self):
"""初始化后处理"""
self.student_id = f"STU{hash(self.name) % 10000:04d}"
@property
def average_grade(self) -> float:
if not self.grades:
return 0.0
return sum(self.grades) / len(self.grades)
# 使用
student = Student("李四", 20)
student.grades.extend([90, 85, 92])
print(student)
# Student(name='李四', age=20, grades=[90.0, 85.0, 92.0], student_id='STU...')
print(f"平均分: {student.average_grade:.1f}")
冻结的数据类
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: float
y: float
point = Point(10.0, 20.0)
# point.x = 15.0 # FrozenInstanceError: 不可修改
排序
from dataclasses import dataclass, field
@dataclass(order=True)
class Product:
sort_index: float = field(init=False, repr=False)
name: str
price: float
def __post_init__(self):
self.sort_index = self.price
products = [
Product("苹果", 5.5),
Product("香蕉", 3.0),
Product("橙子", 4.5)
]
products.sort()
for product in products:
print(f"{product.name}: ¥{product.price}")
# 香蕉: ¥3.0
# 橙子: ¥4.5
# 苹果: ¥5.5
枚举类型
基本枚举
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# 访问
print(Color.RED) # Color.RED
print(Color.RED.name) # RED
print(Color.RED.value) # 1
# 迭代
for color in Color:
print(color)
# 比较
color = Color.RED
if color == Color.RED:
print("是红色")
字符串枚举
from enum import Enum
class HttpStatus(Enum):
OK = "200 OK"
NOT_FOUND = "404 Not Found"
SERVER_ERROR = "500 Internal Server Error"
print(HttpStatus.OK.value) # 200 OK
IntEnum
from enum import IntEnum
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
CRITICAL = 4
# 可以比较大小
print(Priority.HIGH > Priority.MEDIUM) # True
print(Priority.LOW < Priority.CRITICAL) # True
# 可以与整数比较
print(Priority.HIGH == 3) # True
auto()
from enum import Enum, auto
class TaskStatus(Enum):
PENDING = auto()
IN_PROGRESS = auto()
COMPLETED = auto()
FAILED = auto()
print(TaskStatus.PENDING.value) # 1
print(TaskStatus.IN_PROGRESS.value) # 2
枚举方法
from enum import Enum
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
@property
def is_weekend(self):
return self in (Weekday.SATURDAY, Weekday.SUNDAY)
@classmethod
def from_string(cls, day_name: str):
"""从字符串创建枚举"""
try:
return cls[day_name.upper()]
except KeyError:
raise ValueError(f"无效的星期: {day_name}")
# 使用
day = Weekday.from_string("monday")
print(day) # Weekday.MONDAY
print(day.is_weekend) # False
saturday = Weekday.SATURDAY
print(saturday.is_weekend) # True
描述符
描述符是实现了特定协议的类,用于自定义属性访问。
描述符协议
class Descriptor:
def __get__(self, obj, objtype=None):
"""访问属性时调用"""
pass
def __set__(self, obj, value):
"""设置属性时调用"""
pass
def __delete__(self, obj):
"""删除属性时调用"""
pass
类型检查描述符
class Typed:
"""类型检查描述符"""
def __init__(self, name, expected_type):
self.name = name
self.expected_type = expected_type
def __get__(self, obj, objtype=None):
if obj is None:
return self
return obj.__dict__[self.name]
def __set__(self, obj, value):
if not isinstance(value, self.expected_type):
raise TypeError(
f"{self.name} 必须是 {self.expected_type.__name__} 类型"
)
obj.__dict__[self.name] = value
class Person:
name = Typed("name", str)
age = Typed("age", int)
def __init__(self, name, age):
self.name = name
self.age = age
# 使用
person = Person("Alice", 25)
print(person.name) # Alice
# person.age = "twenty" # TypeError: age 必须是 int 类型
属性验证描述符
class ValidatedAttribute:
"""带验证的属性描述符"""
def __init__(self, validator=None):
self.validator = validator
self.data = {}
def __get__(self, obj, objtype=None):
if obj is None:
return self
return self.data.get(id(obj))
def __set__(self, obj, value):
if self.validator:
self.validator(value)
self.data[id(obj)] = value
def __delete__(self, obj):
self.data.pop(id(obj), None)
# 验证函数
def positive_number(value):
if not isinstance(value, (int, float)):
raise TypeError("必须是数字")
if value <= 0:
raise ValueError("必须为正数")
class Product:
price = ValidatedAttribute(positive_number)
quantity = ValidatedAttribute(positive_number)
def __init__(self, price, quantity):
self.price = price
self.quantity = quantity
@property
def total_value(self):
return self.price * self.quantity
# 使用
product = Product(10.5, 100)
print(product.total_value) # 1050.0
# product.price = -5 # ValueError: 必须为正数
懒加载描述符
class LazyProperty:
"""懒加载属性描述符"""
def __init__(self, func):
self.func = func
self.name = func.__name__
def __get__(self, obj, objtype=None):
if obj is None:
return self
# 计算并缓存结果
value = self.func(obj)
setattr(obj, self.name, value)
return value
class Database:
def __init__(self, connection_string):
self.connection_string = connection_string
@LazyProperty
def connection(self):
"""延迟建立数据库连接"""
print("建立数据库连接...")
# 模拟耗时操作
import time
time.sleep(1)
return {"connected": True, "db": "mydb"}
# 使用
db = Database("postgresql://localhost/mydb")
print("第一次访问:")
conn1 = db.connection # 建立数据库连接...
print("第二次访问:")
conn2 = db.connection # 直接使用缓存,不打印
元类
元类是类的类,控制类的创建行为。
基本元类
class Meta(type):
"""自定义元类"""
def __new__(mcs, name, bases, attrs):
"""创建类时调用"""
print(f"创建类: {name}")
# 添加类属性
attrs['created_at'] = '2024-01-01'
return super().__new__(mcs, name, bases, attrs)
def __init__(cls, name, bases, attrs):
"""初始化类时调用"""
print(f"初始化类: {name}")
super().__init__(name, bases, attrs)
class MyClass(metaclass=Meta):
pass
print(MyClass.created_at) # 2024-01-01
单例模式元类
class SingletonMeta(type):
"""单例元类"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
def __init__(self):
print("初始化数据库连接")
self.connected = True
# 使用
db1 = Database() # 初始化数据库连接
db2 = Database() # 不会再次初始化
print(db1 is db2) # True
自动注册元类
class PluginRegistry(type):
"""插件注册元类"""
plugins = {}
def __new__(mcs, name, bases, attrs):
cls = super().__new__(mcs, name, bases, attrs)
# 自动注册非基类
if bases:
plugin_name = attrs.get('plugin_name', name.lower())
mcs.plugins[plugin_name] = cls
return cls
class BasePlugin(metaclass=PluginRegistry):
"""插件基类"""
plugin_name = "base"
def execute(self):
raise NotImplementedError
class EmailPlugin(BasePlugin):
plugin_name = "email"
def execute(self):
return "发送邮件"
class SMSPlugin(BasePlugin):
plugin_name = "sms"
def execute(self):
return "发送短信"
# 查看注册的插件
print(PluginRegistry.plugins)
# {'email': <class 'EmailPlugin'>, 'sms': <class 'SMSPlugin'>}
# 使用
for name, plugin_cls in PluginRegistry.plugins.items():
plugin = plugin_cls()
print(f"{name}: {plugin.execute()}")
属性验证元类
class ValidatedMeta(type):
"""属性验证元类"""
def __new__(mcs, name, bases, attrs):
# 查找验证器
validators = {}
for key, value in attrs.items():
if hasattr(value, 'validator'):
validators[key] = value.validator
cls = super().__new__(mcs, name, bases, attrs)
cls._validators = validators
return cls
def __call__(cls, *args, **kwargs):
instance = super().__call__(*args, **kwargs)
# 验证属性
for attr_name, validator in cls._validators.items():
if hasattr(instance, attr_name):
value = getattr(instance, attr_name)
validator(value)
return instance
def validated_property(validator):
"""装饰器:标记需要验证的属性"""
def decorator(func):
func.validator = validator
return func
return decorator
class User(metaclass=ValidatedMeta):
def __init__(self, username, email, age):
self.username = username
self.email = email
self.age = age
@validated_property(lambda v: len(v) >= 3 or (_ for _ in ()).throw(ValueError("用户名至少3个字符")))
@property
def username(self):
return self._username
@username.setter
def username(self, value):
self._username = value
@validated_property(lambda v: "@" in v or (_ for _ in ()).throw(ValueError("邮箱格式错误")))
@property
def email(self):
return self._email
@email.setter
def email(self, value):
self._email = value
@validated_property(lambda v: 0 <= v <= 150 or (_ for _ in ()).throw(ValueError("年龄范围错误")))
@property
def age(self):
return self._age
@age.setter
def age(self, value):
self._age = value
# 使用
user = User("john", "john@example.com", 25) # ✓
# user = User("jo", "invalid", 200) # ✗ 验证失败
协程和异步编程
async/await 基础
import asyncio
async def say_hello():
"""协程函数"""
print("Hello")
await asyncio.sleep(1) # 非阻塞等待
print("World")
# 运行协程
asyncio.run(say_hello())
并发执行
import asyncio
import time
async def fetch_data(url, delay):
"""模拟网络请求"""
print(f"开始请求: {url}")
await asyncio.sleep(delay)
print(f"完成请求: {url}")
return f"Data from {url}"
async def main():
start = time.time()
# 并发执行
results = await asyncio.gather(
fetch_data("https://api.example.com/users", 2),
fetch_data("https://api.example.com/posts", 3),
fetch_data("https://api.example.com/comments", 1)
)
elapsed = time.time() - start
print(f"\n总耗时: {elapsed:.1f}秒")
print(f"结果: {results}")
asyncio.run(main())
# 总耗时约 3 秒(而不是 6 秒)
任务管理
import asyncio
async def worker(name, duration):
"""工作协程"""
print(f"{name} 开始工作")
await asyncio.sleep(duration)
print(f"{name} 完成工作")
return f"{name} 的结果"
async def main():
# 创建任务
task1 = asyncio.create_task(worker("任务1", 2))
task2 = asyncio.create_task(worker("任务2", 3))
# 等待所有任务完成
results = await asyncio.gather(task1, task2)
print(results)
# 取消任务
task3 = asyncio.create_task(worker("任务3", 10))
await asyncio.sleep(1)
task3.cancel()
try:
await task3
except asyncio.CancelledError:
print("任务3被取消")
asyncio.run(main())
异步上下文管理器
import asyncio
class AsyncResource:
"""异步资源"""
async def __aenter__(self):
print("获取资源")
await asyncio.sleep(1)
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
print("释放资源")
await asyncio.sleep(1)
async def use(self):
print("使用资源")
await asyncio.sleep(1)
async def main():
async with AsyncResource() as resource:
await resource.use()
asyncio.run(main())
异步迭代器
import asyncio
class AsyncCounter:
"""异步计数器"""
def __init__(self, start, end):
self.start = start
self.end = end
self.current = start
def __aiter__(self):
return self
async def __anext__(self):
if self.current >= self.end:
raise StopAsyncIteration
await asyncio.sleep(0.1) # 模拟异步操作
value = self.current
self.current += 1
return value
async def main():
async for number in AsyncCounter(0, 5):
print(number, end=" ")
print()
asyncio.run(main())
# 0 1 2 3 4
实际示例:异步 Web 爬虫
import asyncio
import aiohttp
from typing import List
async def fetch_page(session: aiohttp.ClientSession, url: str) -> str:
"""获取页面内容"""
try:
async with session.get(url) as response:
return await response.text()
except Exception as e:
print(f"请求失败 {url}: {e}")
return ""
async def crawl_urls(urls: List[str]) -> dict:
"""爬取多个URL"""
async with aiohttp.ClientSession() as session:
tasks = [fetch_page(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return {url: content for url, content in zip(urls, results)}
# 使用
urls = [
"https://httpbin.org/delay/1",
"https://httpbin.org/delay/2",
"https://httpbin.org/delay/1"
]
results = asyncio.run(crawl_urls(urls))
for url, content in results.items():
print(f"{url}: {len(content)} bytes")
综合实战
实战1: 响应式数据流
"""
响应式数据流系统
展示生成器、协程和异步编程的综合应用
"""
import asyncio
from typing import AsyncIterator, Callable, Any
from functools import wraps
class DataStream:
"""异步数据流"""
def __init__(self):
self._source = None
self._transforms = []
def from_iterable(self, iterable):
"""从可迭代对象创建流"""
async def source():
for item in iterable:
yield item
self._source = source
return self
def from_async_iterable(self, async_iterable):
"""从异步可迭代对象创建流"""
self._source = async_iterable
return self
def map(self, func: Callable) -> 'DataStream':
"""映射转换"""
self._transforms.append(('map', func))
return self
def filter(self, predicate: Callable) -> 'DataStream':
"""过滤"""
self._transforms.append(('filter', predicate))
return self
def take(self, n: int) -> 'DataStream':
"""取前n个"""
async def take_transform(stream):
count = 0
async for item in stream:
if count >= n:
break
yield item
count += 1
self._transforms.append(('take', take_transform))
return self
async def _build_pipeline(self):
"""构建处理管道"""
if self._source is None:
raise ValueError("未设置数据源")
# 创建基础流
stream = self._source()
# 应用转换
for transform_type, func in self._transforms:
if transform_type == 'map':
stream = self._apply_map(stream, func)
elif transform_type == 'filter':
stream = self._apply_filter(stream, func)
elif transform_type == 'take':
stream = func(stream)
return stream
async def _apply_map(self, stream, func: Callable):
"""应用映射"""
if asyncio.iscoroutinefunction(func):
async for item in stream:
yield await func(item)
else:
async for item in stream:
yield func(item)
async def _apply_filter(self, stream, predicate: Callable):
"""应用过滤"""
if asyncio.iscoroutinefunction(predicate):
async for item in stream:
if await predicate(item):
yield item
else:
async for item in stream:
if predicate(item):
yield item
async def collect(self) -> list:
"""收集所有结果"""
pipeline = await self._build_pipeline()
results = []
async for item in pipeline:
results.append(item)
return results
async def foreach(self, func: Callable):
"""对每个元素执行操作"""
pipeline = await self._build_pipeline()
async for item in pipeline:
if asyncio.iscoroutinefunction(func):
await func(item)
else:
func(item)
# 使用示例
async def main():
# 创建数据流
numbers = list(range(1, 21))
stream = DataStream()
results = await (
stream
.from_iterable(numbers)
.filter(lambda x: x % 2 == 0) # 只要偶数
.map(lambda x: x ** 2) # 平方
.take(5) # 前5个
.collect()
)
print("结果:", results)
# 结果: [4, 16, 36, 64, 100]
# 异步处理
async def slow_square(x):
await asyncio.sleep(0.1)
return x ** 2
stream2 = DataStream()
await (
stream2
.from_iterable([1, 2, 3, 4, 5])
.map(slow_square)
.foreach(lambda x: print(f"处理完成: {x}", end=" "))
)
print()
asyncio.run(main())
实战2: 类型安全的 ORM
"""
类型安全的 ORM 示例
展示数据类、描述符、元类和类型提示的综合应用
"""
from dataclasses import dataclass, field
from typing import TypeVar, Generic, List, Optional, Type
from enum import Enum
T = TypeVar('T')
class FieldType(Enum):
INTEGER = "INTEGER"
TEXT = "TEXT"
REAL = "REAL"
BOOLEAN = "BOOLEAN"
@dataclass
class Column:
"""列定义"""
name: str
field_type: FieldType
primary_key: bool = False
nullable: bool = True
default: any = None
class ModelMeta(type):
"""模型元类"""
def __new__(mcs, name, bases, attrs):
cls = super().__new__(mcs, name, bases, attrs)
# 收集列定义
columns = {}
for attr_name, attr_value in attrs.items():
if isinstance(attr_value, Column):
columns[attr_name] = attr_value
cls._columns = columns
cls._table_name = attrs.get('_table_name', name.lower())
return cls
class Model(metaclass=ModelMeta):
"""模型基类"""
_table_name: str = ""
_columns: dict = {}
@classmethod
def create_table(cls):
"""创建表"""
columns_def = []
for col_name, col in cls._columns.items():
col_def = f"{col_name} {col.field_type.value}"
if col.primary_key:
col_def += " PRIMARY KEY"
if not col.nullable:
col_def += " NOT NULL"
if col.default is not None:
col_def += f" DEFAULT {col.default}"
columns_def.append(col_def)
sql = f"CREATE TABLE IF NOT EXISTS {cls._table_name} ({', '.join(columns_def)})"
print(f"执行SQL: {sql}")
return sql
@classmethod
def insert(cls, **kwargs) -> str:
"""插入记录"""
columns = []
values = []
for key, value in kwargs.items():
if key in cls._columns:
columns.append(key)
if isinstance(value, str):
values.append(f"'{value}'")
else:
values.append(str(value))
sql = f"INSERT INTO {cls._table_name} ({', '.join(columns)}) VALUES ({', '.join(values)})"
print(f"执行SQL: {sql}")
return sql
@classmethod
def select_all(cls) -> str:
"""查询所有记录"""
columns = ', '.join(cls._columns.keys())
sql = f"SELECT {columns} FROM {cls._table_name}"
print(f"执行SQL: {sql}")
return sql
# 定义模型
class User(Model):
_table_name = "users"
id = Column("id", FieldType.INTEGER, primary_key=True)
name = Column("name", FieldType.TEXT, nullable=False)
email = Column("email", FieldType.TEXT, nullable=False)
age = Column("age", FieldType.INTEGER, default=0)
active = Column("active", FieldType.BOOLEAN, default=True)
class Product(Model):
_table_name = "products"
id = Column("id", FieldType.INTEGER, primary_key=True)
name = Column("name", FieldType.TEXT, nullable=False)
price = Column("price", FieldType.REAL, nullable=False)
stock = Column("stock", FieldType.INTEGER, default=0)
# 使用
def main():
# 创建表
User.create_table()
Product.create_table()
print()
# 插入数据
User.insert(name="张三", email="zhang@example.com", age=25)
User.insert(name="李四", email="li@example.com", age=30)
print()
# 查询
User.select_all()
Product.select_all()
print()
# 查看列信息
print("User 表的列:")
for col_name, col in User._columns.items():
print(f" {col_name}: {col.field_type.value}")
if __name__ == "__main__":
main()
实战3: 函数式编程工具库
"""
函数式编程工具库
展示高阶函数、柯里化、组合等函数式编程概念
"""
from typing import Callable, TypeVar, List, Any
from functools import reduce, wraps
A = TypeVar('A')
B = TypeVar('B')
C = TypeVar('C')
# 柯里化
def curry(func: Callable) -> Callable:
"""将函数转换为柯里化形式"""
@wraps(func)
def curried(*args):
if len(args) >= func.__code__.co_argcount:
return func(*args)
return lambda *more_args: curried(*(args + more_args))
return curried
# 示例
@curry
def add(a, b, c):
return a + b + c
add_5 = add(5)
add_5_and_3 = add_5(3)
result = add_5_and_3(2)
print(result) # 10
# 函数组合
def compose(*functions: Callable) -> Callable:
"""组合多个函数"""
def composed(initial_value):
return reduce(lambda acc, f: f(acc), reversed(functions), initial_value)
return composed
# 示例
double = lambda x: x * 2
increment = lambda x: x + 1
square = lambda x: x ** 2
# (x + 1) * 2 然后平方
transform = compose(square, double, increment)
print(transform(5)) # ((5 + 1) * 2) ** 2 = 144
# Pipeline
class Pipeline:
"""数据处理管道"""
def __init__(self, data):
self.data = data
def map(self, func: Callable[[A], B]) -> 'Pipeline':
"""映射"""
if isinstance(self.data, list):
self.data = [func(item) for item in self.data]
else:
self.data = func(self.data)
return self
def filter(self, predicate: Callable[[A], bool]) -> 'Pipeline':
"""过滤"""
if isinstance(self.data, list):
self.data = [item for item in self.data if predicate(item)]
return self
def reduce(self, func: Callable[[B, A], B], initial: B = None) -> B:
"""归约"""
if initial is None:
return reduce(func, self.data)
return reduce(func, self.data, initial)
def sort(self, key: Callable = None, reverse: bool = False) -> 'Pipeline':
"""排序"""
if isinstance(self.data, list):
self.data = sorted(self.data, key=key, reverse=reverse)
return self
def take(self, n: int) -> 'Pipeline':
"""取前n个"""
if isinstance(self.data, list):
self.data = self.data[:n]
return self
def skip(self, n: int) -> 'Pipeline':
"""跳过前n个"""
if isinstance(self.data, list):
self.data = self.data[n:]
return self
def result(self):
"""获取结果"""
return self.data
# 使用示例
def main():
numbers = list(range(1, 21))
# 函数式管道处理
result = (
Pipeline(numbers)
.filter(lambda x: x % 2 == 0) # 只要偶数
.map(lambda x: x ** 2) # 平方
.filter(lambda x: x > 100) # 大于100
.sort(reverse=True) # 降序
.take(5) # 前5个
.result()
)
print("结果:", result)
# 结果: [400, 324, 256, 196, 144]
# 字符串处理
text = "hello world python programming"
words = text.split()
result = (
Pipeline(words)
.map(str.upper) # 转大写
.filter(lambda w: len(w) > 4) # 长度>4
.sort() # 排序
.result()
)
print("单词:", result)
# 单词: ['HELLO', 'PROGRAMMING', 'PYTHON', 'WORLD']
# 数据统计
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
stats = {
"sum": Pipeline(numbers).reduce(lambda x, y: x + y),
"product": Pipeline(numbers).reduce(lambda x, y: x * y),
"max": Pipeline(numbers).reduce(lambda x, y: max(x, y)),
"min": Pipeline(numbers).reduce(lambda x, y: min(x, y)),
}
print("统计:", stats)
if __name__ == "__main__":
main()
小结
| 特性 | 说明 | 使用场景 |
|---|---|---|
| 列表推导式 | 简洁的列表创建 | 数据转换和过滤 |
| 生成器表达式 | 惰性求值 | 大数据处理 |
| 解包操作 | 优雅的值提取 | 变量赋值、函数参数 |
| Walrus 运算符 | 表达式中赋值 | 避免重复计算 |
| Match-case | 模式匹配 | 复杂的条件分支 |
| 类型提示 | 静态类型检查 | 大型项目、API 设计 |
| 数据类 | 简化类定义 | 数据容器、DTO |
| 枚举 | 常量集合 | 状态码、选项 |
| 描述符 | 自定义属性访问 | 验证、懒加载 |
| 元类 | 控制类创建 | 框架开发、ORM |
| 协程 | 异步编程 | IO 密集型任务 |
核心要点:
- 推导式让代码更简洁高效
- 生成器适合处理大数据流
- 解包操作提高代码可读性
- 类型提示增强代码可靠性
- 数据类简化数据容器定义
- 描述符和元类是高级元编程工具
- 异步编程提升 IO 性能
- 函数式编程提供另一种思维方式
掌握这些高级语法将帮助你编写更 Pythonic、更高效的代码!