Python 高级语法

0 阅读22分钟

Python 高级语法

目录


列表推导式进阶

基本回顾

# 基本列表推导式
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、更高效的代码!