====== 第十二章:函数高级特性 ======
===== 本章目标 =====
完成本章学习后,你将能够:
* 理解闭包和装饰器
* 掌握函数柯里化和偏函数
* 使用 functools 模块的工具
* 理解生成器函数
* 掌握上下文管理器
===== 闭包(Closure) =====
==== 什么是闭包 ====
闭包是**引用了外部变量**的函数,即使外部函数已经执行完毕,闭包仍然可以访问这些变量。
def outer_function(x):
def inner_function(y):
return x + y # inner引用了外部变量x
return inner_function
# 创建闭包
add_10 = outer_function(10)
add_20 = outer_function(20)
print(add_10(5)) # 15
print(add_20(5)) # 25
# add_10和add_20各自保存了不同的x值
==== 闭包的应用 ====
# 计数器
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c1 = make_counter()
c2 = make_counter()
print(c1()) # 1
print(c1()) # 2
print(c2()) # 1(独立的计数器)
# 函数记忆化(简单版)
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
===== 装饰器(Decorator) =====
==== 基础装饰器 ====
def my_decorator(func):
def wrapper(*args, **kwargs):
print("函数执行前")
result = func(*args, **kwargs)
print("函数执行后")
return result
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# 函数执行前
# Hello!
# 函数执行后
==== 带参数的装饰器 ====
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
# 输出3次 Hello, Alice!
==== 实用装饰器示例 ====
import time
from functools import wraps
# 计时装饰器
def timer(func):
@wraps(func) # 保留原函数元数据
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} 耗时: {elapsed:.4f}秒")
return result
return wrapper
# 调试装饰器
def debug(func):
@wraps(func)
def wrapper(*args, **kwargs):
args_repr = [repr(a) for a in args]
kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
signature = ", ".join(args_repr + kwargs_repr)
print(f"调用 {func.__name__}({signature})")
result = func(*args, **kwargs)
print(f"{func.__name__} 返回 {result!r}")
return result
return wrapper
# 重试装饰器
def retry(max_attempts=3, delay=1):
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"尝试 {attempts} 失败: {e},{delay}秒后重试...")
time.sleep(delay)
return None
return wrapper
return decorator
===== functools 模块 =====
==== partial - 偏函数 ====
from functools import partial
# 固定某些参数
basetwo = partial(int, base=2)
print(basetwo('10010')) # 18
# 实际应用
import json
print_json = partial(json.dumps, indent=2, ensure_ascii=False)
data = {"name": "中文", "age": 25}
print(print_json(data))
==== reduce ====
from functools import reduce
# 累积计算
nums = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, nums) # 120
# 带初始值
sum_with_initial = reduce(lambda x, y: x + y, nums, 10) # 25
# 找最大值
maximum = reduce(lambda x, y: x if x > y else y, nums)
==== lru_cache ====
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(100)) # 瞬间完成
# 查看缓存信息
print(fibonacci.cache_info())
# CacheInfo(hits=98, misses=101, maxsize=128, currsize=101)
===== 生成器函数 =====
# 生成器函数使用yield代替return
def countdown(n):
while n > 0:
yield n
n -= 1
# 使用
for num in countdown(5):
print(num) # 5, 4, 3, 2, 1
# 生成器表达式
gen = (x ** 2 for x in range(10))
print(sum(gen)) # 285
# yield from:委托给子生成器
def flatten(nested):
for item in nested:
if isinstance(item, list):
yield from flatten(item)
else:
yield item
print(list(flatten([1, [2, [3, 4]], 5]))) # [1, 2, 3, 4, 5]
===== 上下文管理器 =====
# 使用with语句
with open("file.txt") as f:
content = f.read()
# 自定义上下文管理器
class ManagedResource:
def __enter__(self):
print("资源获取")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("资源释放")
return False # 不抑制异常
with ManagedResource() as resource:
print("使用资源")
# 使用contextmanager装饰器
from contextlib import contextmanager
@contextmanager
def managed_file(filename):
print(f"打开文件: {filename}")
f = open(filename, 'w')
try:
yield f
finally:
f.close()
print(f"关闭文件: {filename}")
with managed_file("test.txt") as f:
f.write("Hello")
===== 本章小结 =====
本章我们学习了:
* 闭包的概念和应用
* 装饰器的编写和使用
* functools模块的工具
* 生成器函数的高级用法
* 上下文管理器
下一章:[[python_course:chapter13|第十三章:面向对象编程基础]]