mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
131 字
1 分钟
Python 函数与高级特性
2024-02-01

一、装饰器#

1.1 装饰器基础原理#

import functools
# 装饰器本质:接收函数并返回增强函数的函数
def timer(func):
@functools.wraps(func) # 保留原函数元数据
def wrapper(*args, **kwargs):
import time
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} 耗时: {end - start:.4f}s")
return result
return wrapper
@timer
def slow_function():
import time
time.sleep(1)
# 等价于:slow_function = timer(slow_function)

1.2 带参数的装饰器#

import functools
import time
# 带参数的装饰器:返回装饰器的函数
def retry(max_attempts=3, delay=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < max_attempts - 1:
time.sleep(delay)
raise last_exception
return wrapper
return decorator
@retry(max_attempts=3, delay=2)
def unstable_api():
pass

1.3 类装饰器#

import functools
# 类装饰器:实现 __call__ 方法
class CallCounter:
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"调用次数: {self.count}")
return self.func(*args, **kwargs)
@CallCounter
def my_function():
pass
# 使用场景:缓存、计时、访问控制
class Memoize:
def __init__(self, func):
self.func = func
self.cache = {}
functools.update_wrapper(self, func)
def __call__(self, *args):
if args not in self.cache:
self.cache[args] = self.func(*args)
return self.cache[args]

1.4 装饰器顺序#

# 装饰器从下到上执行
@decorator1 # 第2个执行
@decorator2 # 第1个执行
def func():
pass
# 等价于:func = decorator1(decorator2(func))

二、生成器与迭代器#

2.1 生成器函数#

# 生成器函数:包含 yield 关键字
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 生成器对象
gen = fibonacci(10)
print(type(gen)) # <class 'generator'>
# 迭代获取值
for value in gen:
print(value)
# next() 获取
gen = fibonacci(5)
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 1

2.2 生成器表达式#

# 生成器表达式:惰性求值
gen = (x**2 for x in range(1000000)) # 不占满内存
# 列表推导式:立即求值
lst = [x**2 for x in range(1000000)] # 占用大量内存
# 使用场景对比
# 生成器适合:大数据处理、管道处理
# 列表适合:小数据、需要多次迭代
# 链接生成器
def numbers():
for i in range(10):
yield i
def evens():
for i in numbers():
if i % 2 == 0:
yield i
# itertools 生成器
from itertools import count, cycle, chain, islice, takewhile
# 无限计数器
for i in islice(count(10), 5): # 10, 11, 12, 13, 14
print(i)
# 循环
for i in islice(cycle(['A', 'B']), 5): # A, B, A, B, A
print(i)
# 链式迭代
for i in chain([1, 2], ['a', 'b']): # 1, 2, a, b
print(i)

2.3 迭代器协议#

# 迭代器必须实现 __iter__ 和 __next__
class Counter:
def __init__(self, n):
self.n = n
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current >= self.n:
raise StopIteration
result = self.current
self.current += 1
return result
for i in Counter(3):
print(i) # 0, 1, 2

2.4 send() 与协程#

# send() 与生成器通信
def coroutine():
result = None
while True:
received = yield result
result = received * 2
co = coroutine()
next(co) # 启动协程
print(co.send(10)) # 20
print(co.send(5)) # 10
# close() 关闭协程
co.close()
# throw() 抛出异常
try:
co.throw(ValueError, ValueError("error"))
except ValueError:
pass

三、上下文管理器#

3.1 类实现#

# 实现 __enter__ 和 __exit__
class DatabaseConnection:
def __enter__(self):
print("连接数据库")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("关闭数据库连接")
# 返回 True 抑制异常
return False
with DatabaseConnection() as db:
print("使用数据库")
# 异常处理
class SafeConnection:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
print(f"异常: {exc_val}")
return False # 不抑制异常
return True

3.2 生成器实现#

from contextlib import contextmanager
# 使用生成器实现上下文管理器
@contextmanager
def transaction(connection):
print("开始事务")
try:
yield "tx_handle"
print("提交事务")
except Exception:
print("回滚事务")
raise
with transaction(conn) as tx:
pass
# 清理操作
@contextmanager
def managed_resource(name):
print(f"获取 {name}")
try:
yield name
finally:
print(f"释放 {name}")

3.3 ExitStack 嵌套#

from contextlib import ExitStack
# 多个上下文管理器
with ExitStack() as stack:
conn1 = stack.enter_context(db1_connection())
conn2 = stack.enter_context(db2_connection())
# 自动管理所有资源
# 条件进入
with ExitStack() as stack:
if needs_cache:
cache = stack.enter_context(CacheManager())
if needs_logging:
logger = stack.enter_context(Logger())

四、偏函数与可调用对象#

4.1 functools.partial#

from functools import partial
# 固定函数的部分参数
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(5)) # 125
# 常用场景:回调函数
from functools import partial
def send_email(to, subject, body):
print(f"To: {to}, Subject: {subject}")
send_to_alice = partial(send_email, to="alice@example.com")
send_to_alice(subject="Hello", body="Hi!")

4.2 可调用对象#

# __call__ 使对象可像函数一样调用
class Adder:
def __init__(self, n):
self.n = n
def __call__(self, x):
return self.n + x
add5 = Adder(5)
print(add5(10)) # 15
print(callable(add5)) # True
# 使用场景:带状态的函数
class RateLimiter:
def __init__(self, max_calls, period):
self.max_calls = max_calls
self.period = period
self.calls = []
def __call__(self, func):
import time
now = time.time()
self.calls = [t for t in self.calls if now - t < self.period]
if len(self.calls) >= self.max_calls:
raise Exception("Rate limit exceeded")
self.calls.append(now)
return func()

4.3 lru_cache 缓存#

from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_computation(n):
import time
time.sleep(1)
return n * n
# 缓存管理
print(expensive_computation.cache_info())
# CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)
expensive_computation(10) # 计算
expensive_computation(10) # 使用缓存
print(expensive_computation.cache_info())
# CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
# 清除缓存
expensive_computation.cache_clear()

五、元编程#

5.1 动态创建类#

# type() 动态创建类
MyClass = type('MyClass', (object,), {
'x': 1,
'greet': lambda self: f"Hello, I'm {self.name}"
})
# metaclass 控制类创建
class ModelMeta(type):
_registry = {}
def __new__(mcs, name, bases, attrs):
cls = super().__new__(mcs, name, bases, attrs)
mcs._registry[name] = cls
return cls
class User(metaclass=ModelMeta):
pass
print(ModelMeta._registry) # {'User': <class '__main__.User'>}

5.2 getattrgetattribute#

class Gateway:
def __getattr__(self, name):
# 属性不存在时调用
return f"calling {name}"
def __getattribute__(self, name):
# 每次访问属性都调用
return f"intercepted {name}"
class Lazy:
def __init__(self):
self._data = {}
def __getattr__(self, name):
print(f"Loading {name}")
return self._data.get(name)
def __setattr__(self, name, value):
if name == '_data':
super().__setattr__(name, value)
else:
self._data[name] = value

5.3 描述器协议#

# 描述器:实现 __get__, __set__, __delete__
class Property:
def __init__(self, fget, fset=None):
self.fget = fget
self.fset = fset
def __get__(self, obj, objtype=None):
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError
self.fset(obj, value)
class MyClass:
@Property
def value(self):
return self._value
@value.setter
def value(self, v):
self._value = v

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Python 函数与高级特性
https://blog.souloss.com/posts/interview/python-functions-and-advanced-features/
作者
Souloss
发布于
2024-02-01
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时