python常用的装饰器库_Python中的各种装饰器详解
Python裝飾器,分兩部分,一是裝飾器本身的定義,一是被裝飾器對象的定義。
一、函數式裝飾器:裝飾器本身是一個函數。
1.裝飾函數:被裝飾對象是一個函數
[1]裝飾器無參數:
a.被裝飾對象無參數:
>>> def test(func):
def _test():
print 'Call the function %s().'%func.func_name
return func()
return _test
>>> @test def say():return 'hello world'
>>> say() Call the function say(). 'hello world' >>>
b.被裝飾對象有參數:
>>> def test(func):
def _test(*args,**kw):
print 'Call the function %s().'%func.func_name
return func(*args,**kw)
return _test
>>> @test def left(Str,Len): ??? #The parameters of _test can be '(Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) Call the function left(). 'hello' >>>
[2]裝飾器有參數:
a.被裝飾對象無參數:
>>> def test(printResult=False):
def _test(func):
def __test():
print 'Call the function %s().'%func.func_name
if printResult:
print func()
else:
return func()
return __test
return _test
>>> @test(True) def say():return 'hello world'
>>> say() Call the function say(). hello world >>> @test(False) def say():return 'hello world'
>>> say() Call the function say(). 'hello world' >>> @test() def say():return 'hello world'
>>> say() Call the function say(). 'hello world' >>> @test def say():return 'hello world'
>>> say()
Traceback (most recent call last): ? File "", line 1, in ??? say() TypeError: _test() takes exactly 1 argument (0 given) >>>
由上面這段代碼中的最后兩個例子可知:當裝飾器有參數時,即使你啟用裝飾器的默認參數,不另外傳遞新值進去,也必須有一對括號,否則編譯器會直接將func傳遞給test(),而不是傳遞給_test()
b.被裝飾對象有參數:
>>> def test(printResult=False):
def _test(func):
def __test(*args,**kw):
print 'Call the function %s().'%func.func_name
if printResult:
print func(*args,**kw)
else:
return func(*args,**kw)
return __test
return _test
>>> @test() def left(Str,Len): ??? #The parameters of __test can be '(Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) Call the function left(). 'hello' >>> @test(True) def left(Str,Len): ??? #The parameters of __test can be '(Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) Call the function left(). hello >>>
2.裝飾類:被裝飾的對象是一個類
[1]裝飾器無參數:
a.被裝飾對象無參數:
>>> def test(cls):
def _test():
clsName=re.findall('(\w+)',repr(cls))[-1]
print 'Call %s.__init().'%clsName
return cls()
return _test
>>> @test class sy(object): ??? value=32
>>> s=sy() Call sy.__init(). >>> s <__main__.sy object at> >>> s.value 32 >>>
b.被裝飾對象有參數:
>>> def test(cls):
def _test(*args,**kw):
clsName=re.findall('(\w+)',repr(cls))[-1]
print 'Call %s.__init().'%clsName
return cls(*args,**kw)
return _test
>>> @test class sy(object): ??? def __init__(self,value): ??????????????? #The parameters of _test can be '(value)' in this case. ??????? self.value=value
>>> s=sy('hello world') Call sy.__init(). >>> s <__main__.sy object at> >>> s.value 'hello world' >>>
[2]裝飾器有參數:
a.被裝飾對象無參數:
>>> def test(printValue=True):
def _test(cls):
def __test():
clsName=re.findall('(\w+)',repr(cls))[-1]
print 'Call %s.__init().'%clsName
obj=cls()
if printValue:
print 'value = %r'%obj.value
return obj
return __test
return _test
>>> @test() class sy(object): ??? def __init__(self): ??????? self.value=32
>>> s=sy() Call sy.__init(). value = 32 >>> @test(False) class sy(object): ??? def __init__(self): ??????? self.value=32
>>> s=sy() Call sy.__init(). >>>
b.被裝飾對象有參數:
>>> def test(printValue=True):
def _test(cls):
def __test(*args,**kw):
clsName=re.findall('(\w+)',repr(cls))[-1]
print 'Call %s.__init().'%clsName
obj=cls(*args,**kw)
if printValue:
print 'value = %r'%obj.value
return obj
return __test
return _test
>>> @test() class sy(object): ??? def __init__(self,value): ??????? self.value=value
>>> s=sy('hello world') Call sy.__init(). value = 'hello world' >>> @test(False) class sy(object): ??? def __init__(self,value): ??????? self.value=value
>>> s=sy('hello world') Call sy.__init(). >>>
二、類式裝飾器:裝飾器本身是一個類,借用__init__()和__call__()來實現職能
1.裝飾函數:被裝飾對象是一個函數
[1]裝飾器無參數:
a.被裝飾對象無參數:
>>> class test(object):
def __init__(self,func):
self._func=func
def __call__(self):
return self._func()
>>> @test def say(): ??? return 'hello world'
>>> say() 'hello world' >>>
b.被裝飾對象有參數:
>>> class test(object):
def __init__(self,func):
self._func=func
def __call__(self,*args,**kw):
return self._func(*args,**kw)
>>> @test def left(Str,Len): ??? #The parameters of __call__ can be '(self,Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) 'hello' >>>
[2]裝飾器有參數
a.被裝飾對象無參數:
>>> class test(object):
def __init__(self,beforeinfo='Call function'):
self.beforeInfo=beforeinfo
def __call__(self,func):
def _call():
print self.beforeInfo
return func()
return _call
>>> @test() def say(): ??? return 'hello world'
>>> say() Call function 'hello world' >>>
或者:
>>> class test(object):
def __init__(self,beforeinfo='Call function'):
self.beforeInfo=beforeinfo
def __call__(self,func):
self._func=func
return self._call
def _call(self):
print self.beforeInfo
return self._func()
>>> @test() def say(): ??? return 'hello world'
>>> say() Call function 'hello world' >>>
b.被裝飾對象有參數:
>>> class test(object):
def __init__(self,beforeinfo='Call function'):
self.beforeInfo=beforeinfo
def __call__(self,func):
def _call(*args,**kw):
print self.beforeInfo
return func(*args,**kw)
return _call
>>> @test() def left(Str,Len): ??? #The parameters of _call can be '(Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) Call function 'hello' >>>
或者:
>>> class test(object):
def __init__(self,beforeinfo='Call function'):
self.beforeInfo=beforeinfo
def __call__(self,func):
self._func=func
return self._call
def _call(self,*args,**kw):
print self.beforeInfo
return self._func(*args,**kw)
>>> @test() def left(Str,Len): ??? #The parameters of _call can be '(self,Str,Len)' in this case. ??? return Str[:Len]
>>> left('hello world',5) Call function 'hello' >>>
2.裝飾類:被裝飾對象是一個類
[1]裝飾器無參數:
a.被裝飾對象無參數:
>>> class test(object):
def __init__(self,cls):
self._cls=cls
def __call__(self):
return self._cls()
>>> @test class sy(object): ??? def __init__(self): ??????? self.value=32
>>> s=sy() >>> s <__main__.sy object at> >>> s.value 32 >>>
b.被裝飾對象有參數:
>>> class test(object):
def __init__(self,cls):
self._cls=cls
def __call__(self,*args,**kw):
return self._cls(*args,**kw)
>>> @test class sy(object): ??? def __init__(self,value): ??????? #The parameters of __call__ can be '(self,value)' in this case. ??????? self.value=value
>>> s=sy('hello world') >>> s <__main__.sy object at> >>> s.value 'hello world' >>>
[2]裝飾器有參數:
a.被裝飾對象無參數:
>>> class test(object):
def __init__(self,printValue=False):
self._printValue=printValue
def __call__(self,cls):
def _call():
obj=cls()
if self._printValue:
print 'value = %r'%obj.value
return obj
return _call
>>> @test(True) class sy(object): ??? def __init__(self): ??????? self.value=32
>>> s=sy() value = 32 >>> s <__main__.sy object at> >>> s.value 32 >>>
b.被裝飾對象有參數:
>>> class test(object):
def __init__(self,printValue=False):
self._printValue=printValue
def __call__(self,cls):
def _call(*args,**kw):
obj=cls(*args,**kw)
if self._printValue:
print 'value = %r'%obj.value
return obj
return _call
>>> @test(True) class sy(object): ??? def __init__(self,value): ??????? #The parameters of _call can be '(value)' in this case. ??????? self.value=value
>>> s=sy('hello world') value = 'hello world' >>> s <__main__.sy object at> >>> s.value 'hello world' >>>
總結:【1】@decorator后面不帶括號時(也即裝飾器無參數時),效果就相當于先定義func或cls,而后執行賦值操作func=decorator(func)或cls=decorator(cls);
【2】@decorator后面帶括號時(也即裝飾器有參數時),效果就相當于先定義func或cls,而后執行賦值操作 func=decorator(decoratorArgs)(func)或cls=decorator(decoratorArgs)(cls);
【3】如上將func或cls重新賦值后,此時的func或cls也不再是原來定義時的func或cls,而是一個可執行體,你只需要傳入參數就可調用,func(args)=>返回值或者輸出,cls(args)=>object of cls;
【4】最后通過賦值返回的執行體是多樣的,可以是閉包,也可以是外部函數;當被裝飾的是一個類時,還可以是類內部方法,函數;
【5】另外要想真正了解裝飾器,一定要了解func.func_code.co_varnames,func.func_defaults,通過它們你可以以func的定義之外,還原func的參數列表;另外關鍵字參數是因為調用而出現的,而不是因為func的定義,func的定義中的用等號連接的只是有默認值的參數,它們并不一定會成為關鍵字參數,因為你仍然可以按照位置來傳遞它們。
總結
以上是生活随笔為你收集整理的python常用的装饰器库_Python中的各种装饰器详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android获取文件夹里最新的文件夹,
- 下一篇: iBATIS.NET 学习笔记(五)