关于python装饰器实现的一点疑问( 二 )


■网友
个人理解,仅供参考,将这个装饰函数进行分解def log(func): return wrapperlog函数返回一个wrapper函数def wrapper(*args, **kw): print(\u0026#39;call %s():\u0026#39; % func.__name__) return func(*args, **kw)wrapper函数参数传给func返回带有wrapper函数参数的func原函数。就好比你去银行取钱,插入卡并输入你的密码(参数),ATM(包装函数)将其交银行主机(原函数)进行逻辑处理,吐出钞票(由银行主机处理过的参数的函数)
■网友
装饰器是python里的一个非常有意思的部分,他用于封装函数代码,显式的将封装器应用到被封装的函数上,从而使得他们选择加入到装饰器指定的功能中。对于在函数运行前处理常见前置条件(例如确认授权),或在函数运行后确保清理(输出清除或异常处理),装饰器都非常有用。
是不是感觉听不明白,太绕了!
简单来说,装饰器就是实现了一个通用的功能,然后将这个通用的功能应用到不同的、需要使用这个功能的函数上,从而避免每次都在不同函数上反复写相同的功能代码。
装饰器的本质是一个函数,他接受被装饰的函数作为位置参数,装饰器通过使用该参数来执行某些操作,然后返回一个函数引用,这个函数可以是原始函数,或者是另外一个函数。
我们举例子说明,装饰器是这样的函数,他们接受被装饰的可调用函数作为唯一的参数,并且返回一个可调用函数,
registry = def register(decorated): registry.append(decorated) return decorateddef foo(): return 3foo = register(foo)print(registry)\u0026lt;function foo at 0x00000000025D51E0\u0026gt; register方法是一个简单的装饰器,它把被装饰的函数添加到一个列表中,然后这里是将未改变的被装饰函数返回,可以看出,装饰器一般是传入被装饰函数的引用,然后经过一些指定的处理,最后返回值也是一个函数引用。

还有一种更简单的语法形式:
装饰器的语法糖:我们这里看到的对foo进行装饰的方法是运用
foo = register(foo)语句,还有一种简单的用法是在声明函数的位置应用装饰器,从而使得代码更容易阅读,并且让人立刻意识到使用了装饰器
registry = def register(decorated): registry.append(decorated) return decorated@registerdef foo(x=3): return x@registerdef bar(x=5): return 5for func in registry: print(func())35 再看一个更复杂、更一般化的装饰器函数。装饰器的本质是在执行原有函数(被装饰的函数)的同时,再加上一些额外的功能。
def requires_ints(decorated): def inner(*args, **kwargs): kwarg_values = for arg in list(args) + kwarg_values: if not isinstance(arg, int): raise TypeError(\u0026#39;{} only accepts integers as arguments\u0026#39;.format(decorated.__name__)) return decorated(*args, **kwargs) return inner 在这个装饰器函数requires_ints我们可以看到,他定义了一个内嵌函数inner,这个内嵌函数的参数首先收集被装饰函数的所有参数,然后对其进行判断,判断其是否为整数类型(这就是装饰器添加的额外功能),然后再调用被装饰的函数本身,最后将这个内嵌函数返回。因此当我们再用原函数名进行调用的时候,原来的被装饰函数的引用就能指向这个新的内嵌函数,就能在实现原函数功能的基础上,加上附加的功能了。


推荐阅读