Python高级编程知识体系:从进阶到精通的全面指南
一、序列操作与函数式编程
1. 高级排序技巧
sorted() 与 list.sort() 的深度对比
特性 | sorted() | list.sort() |
---|---|---|
返回值 | 返回新列表 | 原地修改列表,返回None |
适用对象 | 任何可迭代对象 | 仅适用于列表 |
内存使用 | 需要额外内存 | 原地排序,内存效率高 |
稳定性 | 稳定排序(Python 3.11+) | 稳定排序 |
适用场景 | 临时排序、非列表对象 | 大型列表原地排序 |
高级排序示例
# 复合排序:先按长度,再按字母顺序
words = ["banana", "apple", "cherry", "date"]
print(sorted(words, key=lambda x: (len(x), x)))
# 输出: ['date', 'apple', 'banana', 'cherry']
# 按自定义规则排序(模拟SQL中的ORDER BY)
data = [
{
"name": "Alice", "score": 85, "age": 25},
{
"name": "Bob", "score": 92, "age": 22},
{
"name": "Charlie", "score": 85, "age": 30}
]
# 先按分数降序,再按年龄升序
result = sorted(data, key=lambda x: (-x["score"], x["age"]))
print(result)
# 输出: [{'name': 'Bob', 'score': 92, 'age': 22}, {'name': 'Alice', 'score': 85, 'age': 25}, {'name': 'Charlie', 'score': 85, 'age': 30}]
# 使用itemgetter加速排序(比lambda快)
from operator import itemgetter
data = [(1, 'b'), (2, 'a'), (3, 'c')]
print(sorted(data, key=itemgetter(1)))
# 输出: [(2, 'a'), (1, 'b'), (3, 'c')]
2. 高级zip操作
zip的高级用法
# 逆向zip:解包已压缩的序列
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
nums, letters = zip(*pairs)
print(nums) # (1, 2, 3)
print(letters) # ('a', 'b', 'c')
# 填充缺失值(使用itertools.zip_longest)
from itertools import zip_longest
names = ["Alice", "Bob"]
ages = [25, 30, 35]
print(list(zip_longest(names, ages, fillvalue="N/A")))
# 输出: [('Alice', 25), ('Bob', 30), ('N/A', 35)]
# 多序列并行处理
x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9]
print([a + b + c for a, b, c in zip(x, y, z)]) # [12, 15, 18]
# 字典构造
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'New York']
person = dict(zip(keys, values))
print(person) # {'name': 'Alice', 'age': 25, 'city': 'New York'}
3. 高级enumerate应用
enumerate的高级技巧
# 多级枚举:处理嵌套结构
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i, row in enumerate(matrix):
for j, value in enumerate(row):
print(f"matrix[{
i}][{
j}] = {
value}")
# 过滤特定索引的元素
items = ['a', 'b', 'c', 'd', 'e']
filtered = [item for idx, item in enumerate(items) if idx % 2 == 0]
print(filtered) # ['a', 'c', 'e']
# 构建带索引的字典
words = ['apple', 'banana', 'cherry']
word_index = {
word: idx for idx, word in enumerate(words, 1)}
print(word_index) # {'apple': 1, 'banana': 2, 'cherry': 3}
二、装饰器与元编程
1. 装饰器的高级模式
装饰器工厂模式
def retry(max_attempts=3, delay=1):
"""重试装饰器工厂,创建具有指定重试参数的装饰器"""
import time
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise
print(f"Attempt {
attempts} failed: {
str(e)}. Retrying in {
delay} seconds...")
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=5, delay=2)
def fetch_data(url):
"""模拟可能失败的网络请求"""
import random
if random.random() < 0.7: # 70%概率失败
raise ConnectionError("Network error")
return "Data from " + url
# 使用示例
try:
print(fetch_data("https://api.example.com/data"))
except ConnectionError:
print("All attempts failed")
多重装饰器执行顺序
def decorator1(func):
print("Decorator 1 applied")
def wrapper(*args, **kwargs):
print("Decorator 1 before")
result = func(*args, **kwargs)
print("Decorator 1 after")
return result
return wrapper
def decorator2(func):
print("Decorator 2 applied")
def wrapper(*args, **kwargs):
print("Decorator 2 before")
result = func(*args, **kwargs)
print("Decorator 2 after")
return result
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
# 执行顺序:
# 1. 装饰器应用阶段(从下往上):
# - 先应用decorator2
# - 再应用decorator1
# 2. 调用阶段(从外往内):
# - 先执行decorator1的before
# - 再执行decorator2的before
# - 执行原始函数
# - 执行decorator2的after
# - 执行decorator1的after
2. 描述符协议(Descriptors)
描述符是实现了__get__
, __set__
, __delete__
方法的对象,用于控制属性访问。
class TypedProperty:
"""类型验证描述符"""
def __init__(self, name, type_, default=None):
self.name = '_' + name
self.type = type_
self.default = default if default else type_()
def __get__(self, instance, cls):
return getattr(instance, self.name, self.default)
def __set__(self, instance, value):
if not isinstance(value, self.type):
raise TypeError(f"{
self.name[1:]} must be {
self.type.__name__}")
setattr(instance, self.name, value)
def __delete__(self, instance):
raise AttributeError("Can't delete attribute")
class Person:
name = TypedProperty('name', str)
age = TypedProperty('age', int)
height = TypedProperty('height', float)
# 使用示例
p = Person()
p.name = "Alice" # 正确
p.age = 30 # 正确
p.height = 1.75 # 正确
try:
p.age = "thirty" # 引发TypeError
except TypeError as e:
print(e) # _age must be int
描述符类型对比
描述符类型 | 实现方法 | 特点 | 典型应用 |
---|---|---|---|
数据描述符 | 定义__set__ 或__delete__ |
优先级高于实例字典 | property , classmethod , staticmethod |
非数据描述符 | 仅定义__get__ |
优先级低于实例字典 | 函数、方法 |
覆盖型描述符 | 实现__set__ |
实例不能覆盖描述符 | 验证器、类型检查 |
非覆盖型描述符 | 未实现__set__ |
实例可以覆盖描述符 | 只读属性 |
3. 元类(Metaclasses)深入
元类是创建类的类,用于控制类的创建过程。
# 简单的元类示例:自动添加类属性
class AutoInitMeta(type):
"""元类:自动为类添加__init__方法"""
def __new__(mcs, name, bases, namespace):
# 检查是否已有__init__
if '__init__' not in namespace:
# 创建默认的__init__方法
def default_init(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
namespace['__init__'] = default_init
return super().__new__(mcs, name, bases, namespace)
class AutoInitClass(metaclass=AutoInitMeta):
pass
# 使用示例
class Person(AutoInitClass):
pass
p = Person(name="Alice", age=30)
print(p.name, p.age) # Alice 30
# 高级元类:注册子类
class RegistryMeta(type):
"""元类:自动将子类注册到父类"""
_registry = {
}
def __new__(mcs, name, bases, namespace):
cls = super().__new__(mcs, name, bases, namespace)
# 不为基类本身注册
if name != 'RegistryBase':
mcs._registry[name.lower()] = cls
return cls
@classmethod
def get(cls, name):
return cls._registry.get(name.lower())
class RegistryBase(metaclass=RegistryMeta):
@classmethod
def create(cls, type_name, *args, **kwargs):
subclass = cls.get(type_name)
if subclass:
return subclass(*args, **kwargs)
raise ValueError(f"Unknown type: {
type_name}")
class Dog(RegistryBase):
def speak(self):
return "Woof!"
class Cat(RegistryBase):
def speak(self):
return "Meow!"
# 使用示例
dog = RegistryBase.create("dog")
cat = RegistryBase.create("cat")
print(dog.speak(), cat.speak()) # Woof! Meow!
元类应用模式
- 注册模式:自动收集子类(如ORM中的模型注册)
- 接口验证:强制子类实现特定方法
- 单例模式:控制类的实例化
- API版本控制:管理不同版本的类
- 代码生成:动态生成类结构
三、上下文管理器与资源管理
1. 上下文管理器高级模式
可重入上下文管理器
class DatabaseConnection:
"""可重入的数据库连接上下文管理器"""
def __init__(self):
self._connection = None
self._depth = 0 # 嵌套深度计数器
def __enter__(self):
self._depth += 1
if self._connection is None:
print("Opening database connection")
self._connection = "DB_CONNECTION" # 实际连接
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self._depth -= 1
if self._depth == 0 and self._connection is not None:
print("Closing database connection")
self._connection = None
return False # 不吞掉异常
# 使用示例:嵌套使用
db = DatabaseConnection()
with db:
print("First level")
with db:
print("Second level")
# 即使在这里抛出异常,外层也会正确关闭连接
# raise ValueError("Test error")
print("Back to first level")
# 输出:
# Opening database connection
# First level
# Second level
# Back to first level
# Closing database connection
异步上下文管理器
import asyncio
class AsyncDatabase:
"""异步数据库连接管理器"""
async def connect(self):
print("Connecting to database...")
await asyncio.sleep(0.1) # 模拟异步操作
return "DB_CONNECTION"
async def disconnect(self):
print("Disconnecting from database...")
await asyncio.sleep(0.1)
async def __aenter__(self):
self.connection = await self.connect()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.disconnect()
return False
async def main():
async with AsyncDatabase() as db:
print("Using database connection:", db.connection)
# 执行数据库操作
await asyncio.sleep(0.2)
# 运行示例
asyncio.run(main())
2. contextlib高级用法
contextmanager的高级技巧
from contextlib import contextmanager, ExitStack
import time
# 带参数的上下文管理器
@contextmanager
def timing(description: str):
"""测量代码块执行时间的上下文管理器"""
start = time.time()
try:
yield
finally:
elapsed = time.time() - start
print(f"{
description}: {
elapsed:.6f} seconds")
# 使用示例
with timing("List comprehension"):
result = [x * 2 for x in range(1000000)]
# ExitStack:动态管理多个上下文
@contextmanager
def managed_resource(name):
print(f"Acquiring {
name}")
try:
yield name
finally:
print(f"Releasing {
name}")
def use_resources(*resource_names):
with ExitStack() as stack:
resources = [stack.enter_context(managed_resource(name))
for name in resource_names]
print("Using:", ", ".join(resources