# 列表推导式 - 立即创建整个列表 numbers_list = [x * x for x inrange(1000000)] # 消耗大量内存
# 生成器表达式 - 按需生成元素 numbers_gen = (x * x for x inrange(1000000)) # 几乎不消耗额外内存
# 使用生成器表达式处理大文件 defprocess_large_file(filename): withopen(filename, 'r') as file: # 按需处理每一行,不会将整个文件加载到内存 return (line.strip().upper() for line in file if line.strip())
for item in main_generator(): print(item) # 输出: # Start # 1 # 2 # 3 # End
yield from不仅可以简化代码,还可以正确处理子生成器的return值和异常。
技巧4:使用生成器实现协程
在Python 3.5之前,生成器是实现协程的主要方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defconsumer(): result = None whileTrue: value = yield result result = f"Consumed {value}"
defproducer(consumer): consumer.send(None) # 启动生成器 for i inrange(3): value = f"value {i}" result = consumer.send(value) print(f"Producer got: {result}")
c = consumer() producer(c) # 输出: # Producer got: Consumed value 0 # Producer got: Consumed value 1 # Producer got: Consumed value 2
classCustomRange: def__init__(self, start, end, step=1): self.start = start self.end = end self.step = step def__iter__(self): current = self.start while current < self.end: yield current current += self.step
# 使用 for num in CustomRange(1, 10, 2): print(num) # 输出: 1, 3, 5, 7, 9
这比实现传统的迭代器(需要__iter__和__next__方法)简单得多。
技巧9:使用生成器进行惰性评估
生成器可以实现惰性评估,只在需要结果时才执行计算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defexpensive_calculation(x): print(f"Computing {x}...") return x * x
# 立即计算所有值 eager_results = [expensive_calculation(x) for x inrange(5)] print("Eager evaluation done")
# 惰性计算 lazy_results = (expensive_calculation(x) for x inrange(5)) print("Lazy evaluation set up")
# 只有在这里才会执行计算 for result in lazy_results: print(f"Got result: {result}")
这种方法在处理大型数据集或昂贵的计算时特别有用。
技巧10:使用生成器实现状态机
生成器可以优雅地实现状态机:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defparse_csv(file_path): withopen(file_path, 'r') as file: # 状态: 读取标题 header = next(file).strip().split(',') yield header # 状态: 读取数据行 for line in file: ifnot line.strip(): continue data = line.strip().split(',') yielddict(zip(header, data))
# 使用 for item in parse_csv('data.csv'): print(item)