语言语法糖_Python装饰器本质上是对函数闭包的语法糖

Python装饰器本质上是对函数闭包的语法糖

  • 函数闭包

    • 把主要逻辑和辅助功能写在同一个函数里: 难以修改,容易出bug

    • 通过辅助功能函数调用主要功能函数: 函数逻辑反了,难以封装成模块

    • 函数闭包: 需要显式调用函数闭包

    • 装饰器: 其实就是函数闭包,只是不用显式调用了而已

  • 装饰器

    • 装饰器本质上是对函数闭包的语法糖

    • 装饰器在第一次调用被装饰的函数时调用闭包进行函数增强

    • 一个通用的装饰器: 保留原函数的参数列表和返回值

  • 一道面试题: 多个装饰器的执行顺序

  • 一道思考题: 如何创建带参数的装饰器


装饰器是Python中的一个容易令人困惑的概念,但实际上,只要掌握两句口诀,就可以掌握装饰器,搞定那些令人困惑的面试题.

  • 装饰器本质上是对函数闭包的语法糖.

  • 装饰器在第一次调用被装饰的函数时调用闭包进行函数增强.

函数闭包

函数闭包本质上是一个函数,它的接收参数和返回值也都是函数,返回的函数本质上是对传入的参数进行增强之后的结果.

下面,我们从一个例子来引入函数闭包:

假设我们有一个主要需求(主要功能): 统计0~100之间的所有奇数,还有一个额外的需求(辅助功能):统计函数运行的时间,我们从各种不同的写法,来引入闭包.

把主要逻辑和辅助功能写在同一个函数里: 难以修改,容易出bug

假设我们不使用任何函数增强技术,将所有代码写入一个文件里,代码如下:

import time

def print_odds():
"""
输出0~100之间所有奇数,并统计函数执行时间
"""
start_time = time.clock() # 起始时间
# 查找并输出所有奇数
for i in range(100):
if i % 2 == 1:
print(i)
end_time = time.clock() # 结束时间
print("it takes {} s to find all the olds".format(end_time - start_time))

if __name__ == '__main__':
print_odds()

上述代码奇丑无比,它之所以丑,是因为把主要功能逻辑(输出奇数)和辅助功能(记录时间)耦合在一起了,这样会导致程序的可读性很差,且难以修改,容易出bug.

通过辅助功能函数调用主要功能函数: 函数逻辑反了,难以封装成模块

对上面的代码加以改进,既然要解耦合,就将主要功能逻辑(输出奇数)和辅助功能(记录时间)分到两个函数里就好了,通过函数调用(将主要功能逻辑print_odds传入辅助函数count_time,在辅助函数内部调用主要功能逻辑)来实现功能.

import time

def count_time(func):
"""
统计某个函数的运行时间
"""
start_time = time.clock() # 起始时间
func() # 执行函数
end_time = time.clock() # 结束时间
print("it takes {} s to find all the olds".format(end_time - start_time))

def print_odds():
"""
输出0~100之间所有奇数,并统计函数执行时间
"""
for i in range(100):
if i % 2 == 1:
print(i)

if __name__ == '__main__':
count_time(print_odds)

这个代码好在解耦合了,方便对主要功能逻辑和辅助功能逻辑分别进行修改.

上述程序可以正常执行,在语法上没有问题,但是在逻辑上是存在问题的,它违反了设计模式中的开闭原则: 在main函数里调用了count_time.模块的主要功能函数print_odds应该是对使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值