Python惰性求值模式
# Python 惰性求值模式 —— 需要时才计算节省内存提升性能# 生成器、迭代器、描述符是实现惰性求值的主要工具import itertools# 1. 生成器基础惰性求值def fibonacci_up_to(limit):斐波那契数列生成器 —— 每次迭代只计算一个值a, b 0, 1while a limit:yield aa, b b, a bfib fibonacci_up_to(1000)print(前 5 个:, [next(fib) for _ in range(5)])print(全部:, list(fibonacci_up_to(100)))# 2. 惰性属性描述符class LazyProperty:属性仅在首次访问时计算然后缓存到实例字典def __init__(self, func): self.func func; self.name func.__name__def __get__(self, instance, owner):if instance is None: return selfvalue self.func(instance)instance.__dict__[self.name] valuereturn valueclass DataAnalyzer:def __init__(self, data): self.data dataLazyPropertydef sorted_data(self): print(排序...); return sorted(self.data)LazyPropertydef mean(self): print(计算均值...); return sum(self.data) / len(self.data)LazyPropertydef median(self):n len(self.sorted_data); mid n // 2return self.sorted_data[mid] if n % 2 else \(self.sorted_data[mid-1] self.sorted_data[mid]) / 2da DataAnalyzer([3, 1, 4, 1, 5, 9, 2, 6])print(mean(首次):, da.mean, mean(再次-缓存):, da.mean)# 3. itertools 惰性序列counter itertools.count(start1, step2)print(前 5 奇数:, [next(counter) for _ in range(5)])def primes_upto(n):惰性素数生成器 —— takewhile 控制无限流终止def is_prime(x):if x 2: return Falsefor i in range(2, int(x**0.5)1):if x % i 0: return Falsereturn Truereturn itertools.takewhile(lambda x: x n, filter(is_prime, itertools.count(2)))print(50 以内素数:, list(primes_upto(50)))# 4. 自定义惰性序列__iter__/__next__ 协议class LazySequence:只在请求时生成支持索引访问触发计算直到目标位置def __init__(self, gen_func, *args):self._gen_func gen_func; self._args argsself._generator None; self._cache []def __iter__(self): return selfdef __next__(self):if self._generator is None:self._generator self._gen_func(*self._args)value next(self._generator)self._cache.append(value); return valuedef __getitem__(self, index):while len(self._cache) index: next(self)return self._cache[index]lazy_sq LazySequence(lambda n: (i**2 for i in range(n)), 100)print(lazy[10]:, lazy_sq[10], lazy[5](缓存):, lazy_sq[5])# 5. 惰性读取大文件逐行读取不加载整个文件def read_lines_lazy(filepath):with open(filepath, r, encodingutf-8) as f:for line in f: yield line.rstrip(\n)# 6. 延迟计算包装器class Deferred:def __init__(self, func, *args, **kwargs):self._func func; self._args argsself._kwargs kwargs; self._value None; self._done Falsedef __call__(self):if not self._done:self._value self._func(*self._args, **self._kwargs)self._done Truereturn self._valueconfig Deferred(lambda p: {host: localhost, port: 8080}, /etc/app.ini)print(首次:, config(), 再次(缓存):, config())