Python进阶教程:装饰器与生成器深入
🕒 阅读时间:7 分钟📝 字数:1066👀 阅读量:Loading...
本文摘要
本篇深入讲解了装饰器(基础、带参数、内置装饰器)和生成器(基础、表达式、无限序列),并用手写缓存装饰器串联实战。理解这两个特性,能写出更简洁、更 Pythonic 的代码。
目录
本文是 Python 入门教程系列 的第 13 篇(扩展篇)。装饰器和生成器是 Python 中非常优雅的两个特性,本篇深入讲解。
一、函数是一等公民
在 Python 中,函数可以像变量一样传递和返回,这是装饰器的基础:
def greet(name): return f"你好,{name}"
# 函数可以赋值给变量say = greetprint(say("张三")) # 你好,张三
# 函数可以作为参数传递def call_twice(func, arg): return func(func(arg))
print(call_twice(greet, "张三")) # 你好,你好,张三二、装饰器基础
装饰器可以在不修改原函数的情况下增强函数功能:
import time
def timer(func): """统计函数执行时间的装饰器""" def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start print(f"{func.__name__} 耗时 {elapsed:.4f}s") return result return wrapper
@timerdef slow_add(a, b): time.sleep(0.1) return a + b
print(slow_add(1, 2)) # slow_add 耗时 0.1xxx s 3三、带参数的装饰器
import functools
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(times=3)def say_hello(): print("Hello!")
say_hello() # 打印 3 次 Hello!四、常用内置装饰器
class MyClass: class_var = 0
def __init__(self, value): self._value = value
@property def value(self): """只读属性""" return self._value
@value.setter def value(self, new_val): """属性赋值检查""" if new_val < 0: raise ValueError("不能为负") self._value = new_val
@classmethod def create(cls): """类方法""" return cls(0)
@staticmethod def helper(): """静态方法""" return "工具函数"
obj = MyClass(10)print(obj.value) # 10obj.value = 20 # 调用 setterprint(obj.value) # 20print(MyClass.create().value) # 0print(MyClass.helper()) # 工具函数五、生成器基础
生成器用 yield 逐次产出值,不一次性占用内存:
def count_up_to(n): i = 1 while i <= n: yield i # 暂停并返回 i += 1
gen = count_up_to(5)print(next(gen)) # 1print(next(gen)) # 2print(list(gen)) # [3, 4, 5] 继续消费剩余六、生成器表达式
# 列表推导式 vs 生成器表达式squares_list = [x*x for x in range(1000000)] # 立即占用内存squares_gen = (x*x for x in range(1000000)) # 惰性求值
# 生成器可以传给 sum 等函数print(sum(x*x for x in range(10))) # 285
# 内存对比import sysprint(sys.getsizeof([x for x in range(100000)])) # 约 800KBprint(sys.getsizeof((x for x in range(100000)))) # 约 112B七、生成器实战:无限序列
def fibonacci(): """无限斐波那契序列生成器""" a, b = 0, 1 while True: yield a a, b = b, a + b
fib = fibonacci()# 取前 10 个print([next(fib) for _ in range(10)])# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]八、实战:缓存装饰器
import functoolsimport time
def memoize(func): """手写缓存装饰器""" cache = {}
@functools.wraps(func) def wrapper(*args): if args not in cache: cache[args] = func(*args) return cache[args] return wrapper
@memoizedef expensive(n): print(f"计算 {n}...") time.sleep(1) return n * n
start = time.perf_counter()print(expensive(5)) # 计算 5... 25print(expensive(5)) # 直接命中缓存 25(不打印计算)print(f"耗时:{time.perf_counter()-start:.1f}s") # 约 1s总结
本篇深入讲解了装饰器(基础、带参数、内置装饰器)和生成器(基础、表达式、无限序列),并用手写缓存装饰器串联实战。理解这两个特性,能写出更简洁、更 Pythonic 的代码。
Python进阶教程:装饰器与生成器深入
作者:Wang Shijie
本文链接:https://wsj-blog.pages.dev/posts/python-jin-jie-jiao-cheng-zhuang-shi-qi-yu-sheng-cheng-qi/
本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
留言评论
评论资源加载失败,请重试。