装饰器的本质是一个高阶函数,它接收一个函数作为参数,并返回一个新函数来替代原函数。这个新函数需要:
- 保留原函数的调用方式(参数和返回值)。
- 在原函数执行前后添加额外逻辑(如计时、日志等)。
因此,我们需要在装饰器内部定义一个新函数来实现这些功能。
装饰器的执行流程为:
- 定义装饰器函数
display_time:它接收一个函数func作为参数,并返回wrapper函数。 - 定义被装饰函数
prime_nums:此时prime_nums是一个普通函数对象。 - 应用装饰器:Python 自动将
prime_nums作为参数传递给display_time,即执行display_time(prime_nums)。 - 替换原函数:
display_time返回wrapper函数,Python 用这个新函数覆盖了原来的prime_nums。
也就是说装饰后,原函数名指向wrapper,而非原始函数。
当你调用prime_nums()时,实际上执行的是wrapper(),它会:
- 记录开始时间
- 调用
func()(即原函数) - 记录结束时间并打印耗时
这种等价的设计,会让初学者搞不懂为什么突然可以采取这种优雅的写法,类似的写法还有很多,在python中叫做语法糖:通过规范的写法来让代码更加优美和简洁,比如列表推导式也是,我们在后面再提。
你可以把@理解为语法糖操作,实际上并非是@装饰器,而是@装饰器+下一行的代码 二者是一个整体
@浙大疏锦行