Python高级特性:生成器、迭代器、闭包与装饰器
1. 生成器(Generator)
1.1 生成器概念
生成器是Python中一种特殊的迭代器,它可以让我们以一种更优雅的方式构造迭代器。生成器不会一次性生成所有数据,而是在需要时才生成数据,这样可以节省内存空间。
1.2 创建生成器的方法
1.2.1 使用生成器表达式
# 列表推导式
numbers = [x * x for x in range(10)] # 创建列表
# 生成器表达式
generator = (x * x for x in range(10)) # 创建生成器
1.2.2 使用yield关键字
def fibonacci(num):
"""生成斐波那契数列的生成器"""
a, b = 0, 1
for _ in range(num):
yield b
a, b = b, a + b
# 使用生成器
fib = fibonacci(10)
for num in fib:
print(num)
1.3 生成器的特性与方法
1.3.1 next()方法
generator = (x for x in range(3))
print(next(generator)) # 0
print(next(generator)) # 1
print(next(generator)) # 2
# print(next(generator)) # StopIteration
1.3.2 send()方法
def counter():
i = 0
while True:
value = yield i
if value is not None:
i = value
else:
i += 1
c = counter()
print(next(c)) # 0
print(c.send(10)) # 10
print(next(c)) # 11
1.4 生成器的优势
- 内存效率:按需生成数据
- 代码简洁:比迭代器的实现更简单
- 状态保存:保存上次运行状态
2. 迭代器(Iterator)
2.1 迭代器概念
迭代器是一个可以记住遍历位置的对象,它必须实现__iter__()
和__next__()
方法。
2.2 可迭代对象与迭代器的区别
from collections.abc import Iterable, Iterator
# 可迭代对象示例
print(isinstance([], Iterable)) # True
print(isinstance({}, Iterable)) # True
print(isinstance('abc', Iterable)) # True
# 转换为迭代器
lst = [1, 2, 3]
iter_lst = iter(lst)
print(isinstance(iter_lst, Iterator)) # True
2.3 自定义迭代器
class CountDown:
def __init__(self, start):
self.start = start
def __iter__(self):
return self
def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1
# 使用自定义迭代器
counter = CountDown(5)
for num in counter:
print(num) # 5, 4, 3, 2, 1
3. 闭包(Closure)
3.1 闭包的定义
闭包是指延伸了作用域的函数,它可以访问定义函数时存在的非局部变量。
3.2 闭包的条件
- 必须有内嵌函数
- 内嵌函数必须引用外部函数的变量
- 外部函数必须返回内嵌函数
3.3 闭包示例
def make_averager():
count = 0
total = 0
def averager(new_value):
nonlocal count, total
count += 1
total += new_value
return total / count
return averager
avg = make_averager()
print(avg(10)) # 10.0
print(avg(20)) # 15.0
print(avg(30)) # 20.0
3.4 闭包中的变量作用域
def outer(x):
def inner():
nonlocal x # 使用nonlocal关键字修改外部变量
x += 1
return x
return inner
counter = outer(0)
print(counter()) # 1
print(counter()) # 2
4. 装饰器(Decorator)
4.1 装饰器基础
装饰器是可调用的对象,它接收一个函数作为参数并返回一个函数,用于增强函数功能。
4.2 简单装饰器
import functools
import time
def timer(func):
@functools.wraps(func) # 保留原函数的元信息
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Function {func.__name__} took {end-start} seconds")
return result
return wrapper
@timer
def slow_function(n):
time.sleep(n)
return n
slow_function(1) # Function slow_function took 1.0 seconds
4.3 带参数的装饰器
def repeat(times):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}")
greet("World") # 打印三次 Hello, World
4.4 类装饰器
class Singleton:
def __init__(self, cls):
self._cls = cls
self._instance = None
def __call__(self, *args, **kwargs):
if self._instance is None:
self._instance = self._cls(*args, **kwargs)
return self._instance
@Singleton
class Database:
def __init__(self):
print("数据库连接创建")
# 测试单例模式
db1 = Database()
db2 = Database()
print(db1 is db2) # True
5. 最佳实践与注意事项
5.1 生成器最佳实践
- 处理大数据集时优先使用生成器
- 注意捕获StopIteration异常
- 合理使用send()方法进行双向通信
5.2 迭代器使用建议
- 优先使用for循环而不是手动调用next()
- 实现自定义迭代器时记得同时实现__iter__和__next__方法
- 注意处理迭代完成的情况
5.3 闭包使用技巧
- 谨慎使用nonlocal关键字
- 注意闭包占用的内存资源
- 合理利用闭包实现数据隐藏
5.4 装饰器编写原则
- 保持装饰器的通用性
- 使用functools.wraps保留原函数信息
- 考虑装饰器的性能影响