首页 > 代码库 > Python之装饰器
Python之装饰器
Python之装饰器
装饰器
先来看一个例子,一个函数f1接收另一个函数f2作为参数,并将该参数f2返回给f2:
def deco(func): print("before myfunc() called.") func() print("after myfunc() called.") return funcdef myfunc(): print("myfunc() called.")myfunc = deco(myfunc)myfunc()myfunc()
可以使用装饰器(Decorator)语法糖来简化代码:
def deco(func): print("before myfunc() called.") func() print("after myfunc() called.") return func@decodef myfunc(): print("myfunc() called.")myfunc()myfunc()
跟上面的代码完全一样,也就是说在定义一个函数(比如foo)的时候,加上@deco,就等同于:foo = deco(foo)
简单的看上面的代码似乎没什么价值,无非就是在Decorator中接收一个函数作为参数,并返回给作为参数的函数本身。
但如果我们在Decorator中内嵌定义一个新的函数,并将这个新的函数返回给作为参数的函数,那就不一样了,例如:
def deco(func): def _newfunc(): print("before myfunc() called.") func() print("after myfunc() called.") # 不需要返回func,实际上应返回原函数的返回值 return _newfunc@decodef myfunc(): print("myfunc() called.") return ‘ok‘myfunc()
在这里,myfunc()函数永久的失去了,后续调用myfunc(),真正调用的其实是在Decorator中返回的函数。
可见,Decorator实际上就是一个函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问。
Decorator是在函数之上的修饰,这些修饰仅是当声明一个函数或者方法的时候,才会应用的额外调用。
装饰带参数的函数
上面的例子Decorator装饰的参数都是无参的,下面来看如何装饰带参数的函数,
def deco(func): def _newfunc(a, b): print("before myfunc() called.") ret = func(a, b) print("after myfunc() called. result: %s" % ret) return ret return _newfunc@decodef myfunc(a, b): print("myfunc(%s,%s) called." % (a, b)) return a + bmyfunc(1, 2)
如果被装饰函数的参数个数不确定呢,即可变参数的情况:
def deco(func): def _newfunc(*args, **kwargs): print("before %s called." % func.__name__) ret = func(*args, **kwargs) print("after %s called. result: %s" % (func.__name__, ret)) return ret return _newfunc@decodef myfunc(a, b=8, c=1): print("myfunc2(%s,%s,%s) called." % (a, b, c)) return a+b+cmyfunc(1)myfunc(1, 4)myfunc(1, 10, 9)
只要在装饰器中的内嵌函数使用可变参数列表(*args、**kwargs)即可。
装饰器自身带参数
这种情况需要嵌套两层函数:
def deco(arg): def _deco(func): def _newfunc(): print("before %s called [%s]." % (func.__name__, arg)) func() print("after %s called [%s]." % (func.__name__, arg)) return _newfunc return _deco@deco("mymodule")def myfunc(): print("myfunc() called.")myfunc()
如果装饰器的参数是类类型:
class locker: def __init__(self): print("locker.__init__() should be not called.") @staticmethod def acquire(): print("locker.acquire() called.(这是静态方法)") @staticmethod def release(): print(" locker.release() called.(不需要对象实例)")def deco(cls): ‘‘‘cls 必须实现acquire和release静态方法‘‘‘ def _deco(func): def __deco(): print("before %s called [%s]." % (func.__name__, cls)) cls.acquire() try: return func() finally: cls.release() return __deco return _deco@deco(locker)def myfunc(): print(" myfunc() called.")myfunc()
同时使用多个装饰器
class mylocker: def __init__(self): print("mylocker.__init__() called.") @staticmethod def acquire(): print("mylocker.acquire() called.") @staticmethod def unlock(): print(" mylocker.unlock() called.")class lockerex(mylocker): @staticmethod def acquire(): print("lockerex.acquire() called.") @staticmethod def unlock(): print(" lockerex.unlock() called.")def lockhelper(cls): ‘‘‘cls 必须实现acquire和release静态方法‘‘‘ def _deco(func): def __deco(*args, **kwargs): print("before %s called." % func.__name__) cls.acquire() try: return func(*args, **kwargs) finally: cls.unlock() return __deco return _decoclass example: @lockhelper(mylocker) def myfunc(self): print(" myfunc() called.") @lockhelper(mylocker) @lockhelper(lockerex) def myfunc2(self, a, b): print(" myfunc2() called.") return a + ba = example()a.myfunc()print(a.myfunc())print(a.myfunc2(1, 2))print(a.myfunc2(3, 4))
Python之装饰器
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。