本文实例讲述了Python装饰器用法。分享给大家供大家参考,具体如下:
写装饰器
装饰器只不过是一种函数,接收被装饰的可调用对象作为它的唯一参数,然后返回一个可调用对象(就像前面的简单例子)
注意重要的一点,当装饰器被应用到被装饰函数上时,装饰器代码本身就会运行,而不是当被装饰函数被调用时.理解这个很关键,接下来的几个例子的讲解过程也会变得很清楚
第一个例子: 函数注册
看下面简单的函数注册:
registry = []def register(decorated): registry.append(decorated) return decorated
注册器方法是一个简单的装饰器。它追加位置参数,也就是被装饰函数到registry变量中,然后不做改变地返回被装饰方法。任何接受register装饰器的方法会把它自己追加到registry变量上。
@registerdef foo(): return 3@registerdef bar(): return 5
如果你访问了registry,可以很容易地在上面迭代并执行里面的函数。
answers = []for func in registry: answers.append(func())
answers 列表现在回包含 [3, 5]. 这是因为函数已按次序执行,并且它们的返回值被追加到 answers中.
对于现有的函数注册,有几类简单的应用,例如添加“钩子(hooks)”到代码中,这样的话自定义的功能在条件事件之前或之后运行。 下面的Registry类能够处理这种情况:
class Registry(object): def __init__(self): self._functions = [] def register(self, decorated): self._functions.append(decorated) return decorated def run_all(self, *args, **kwargs): return_values = [] for func in self._functions: return_values.append(func(*args, **kwargs)) return return_values
这个类里的register方法让然像之前一样按同样方法工作。用一个绑定(bound)的方法作为装饰器完全没问题。它接收self作为第一参数(像任何绑定方法一样),并且需要一个额外的位置参数,那就是被装饰函数,通过创建几个不同的 registry实例,你可以拥有一些完全分开的注册器。使用相同函数并且,用超过一个注册器注册它也是可行的,像下面展示的一样 :
a = Registry()b = Registry()@a.registerdef foo(x=3): return x@b.registerdef bar(x=5): return x@a.register@b.registerdef baz(x=7): return x
运行两个注册器的run_alll方法,得到如下结果:
a.run_all() # [3, 7]b.run_all() # [5, 7]
注意,run_all 方法能够使用参数,当它们运行时会把参数传给内部函数
a.run_all(x=4) # [4, 4]
运行时包装代码
以上这些装饰器都很简单,因为被装饰方法被传递后未经更改。然而,有些时候当被装饰方法执行时,你想要运行额外的功能。你通过返回一个添加了相关功能并且在它执行过程中调用被装饰方法的不同的可调用对象来实现。
新闻热点
疑难解答