Python 参数化装饰器

时间:2019-04-18
本文章向大家介绍Python 参数化装饰器,主要包括Python 参数化装饰器使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在解析源码中的装饰器时,Python 会把被装饰的函数作为第一个参数传给装饰器函数,那怎么让装饰器接受其他参数呢? 

答案是建立一个装饰器工厂函数,返回一个装饰器,然后再把它应用到要装饰的函数上。

举例:

# BEGIN REGISTRATION

registry = []  # <1>

def register(func):  # <2>
    print('running register(%s)' % func)  # <3>
    registry.append(func)  # <4>
    return func  # <5>

@register  # <6>
def f1():
    print('running f1()')

@register
def f2():
    print('running f2()')

def f3():  # <7>
    print('running f3()')

def main():  # <8>
    print('running main()')
    print('registry ->', registry)
    f1()
    f2()
    f3()

if __name__=='__main__':
    main()  # <9>

# END REGISTRATION

为了便于 register 执行的函数注册供能,我们提供一个可选的 active 参数,设为 False 时,不注册被装饰的函数。

# BEGIN REGISTRATION_PARAM

registry = set()  # <1>

def register(active=True):  # <2>
    def decorate(func):  # <3>
        print('running register(active=%s)->decorate(%s)'
              % (active, func))
        if active:   # <4>
            registry.add(func)
        else:
            registry.discard(func)  # <5>

        return func  # <6>
    return decorate  # <7>

@register(active=False)  # <8>
def f1():
    print('running f1()')

@register()  # <9>
def f2():
    print('running f2()')

def f3():
    print('running f3()')

# END REGISTRATION_PARAM

如上所示,新的 register 函数不是装饰器,而是装饰器工厂函数,调用它会返回真正的装饰器,这才是应用到目标函数的装饰器。

只有 f2 函数在 register 中,f1 不在其中,因为传给 register 装饰器工厂函数的参数时 active = False,所以应用到 f1 上的 decorate 没有把它添加到 registry 中。decorate 是装饰器,register 是装饰器工厂函数。