Python裝飾器,分兩部分,一是裝飾器本身的定義,一是被裝飾器對(duì)象的定義。
一、函數(shù)式裝飾器:裝飾器本身是一個(gè)函數(shù)。
1.裝飾函數(shù):被裝飾對(duì)象是一個(gè)函數(shù)
[1]裝飾器無參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @test
def say():return 'hello world'
>>> say()
Call the function say().
'hello world'
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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]裝飾器有參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @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 "<pyshell#224>", line 1, in <module>
say()
TypeError: _test() takes exactly 1 argument (0 given)
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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
>>>
[1]裝飾器無參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @test
class sy(object):
value=32
>>> s=sy()
Call sy.__init().
>>> s
<__main__.sy object at 0x0000000002C3E390>
>>> s.value
32
>>>
>>> @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 0x0000000003AF7748>
>>> s.value
'hello world'
>>>
a.被裝飾對(duì)象無參數(shù):
>>> @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.被裝飾對(duì)象有參數(shù):
>>> @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().
>>>
二、類式裝飾器:裝飾器本身是一個(gè)類,借用__init__()和__call__()來實(shí)現(xiàn)職能
1.裝飾函數(shù):被裝飾對(duì)象是一個(gè)函數(shù)
[1]裝飾器無參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @test
def say():
return 'hello world'
>>> say()
'hello world'
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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]裝飾器有參數(shù)
a.被裝飾對(duì)象無參數(shù):
>>> @test()
def say():
return 'hello world'
>>> say()
Call function
'hello world'
>>>
或者:
>>> @test()
def say():
return 'hello world'
>>> say()
Call function
'hello world'
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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'
>>>
或者:
>>> @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'
>>>
[1]裝飾器無參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @test
class sy(object):
def __init__(self):
self.value=32
>>> s=sy()
>>> s
<__main__.sy object at 0x0000000003AAFA20>
>>> s.value
32
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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 0x0000000003AAFA20>
>>> s.value
'hello world'
>>>
[2]裝飾器有參數(shù):
a.被裝飾對(duì)象無參數(shù):
>>> @test(True)
class sy(object):
def __init__(self):
self.value=32
>>> s=sy()
value = 32
>>> s
<__main__.sy object at 0x0000000003AB50B8>
>>> s.value
32
>>>
b.被裝飾對(duì)象有參數(shù):
>>> @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 0x0000000003AB5588>
>>> s.value
'hello world'
>>>
總結(jié):【1】@decorator后面不帶括號(hào)時(shí)(也即裝飾器無參數(shù)時(shí)),效果就相當(dāng)于先定義func或cls,而后執(zhí)行賦值操作func=decorator(func)或cls=decorator(cls);
【2】@decorator后面帶括號(hào)時(shí)(也即裝飾器有參數(shù)時(shí)),效果就相當(dāng)于先定義func或cls,而后執(zhí)行賦值操作 func=decorator(decoratorArgs)(func)或cls=decorator(decoratorArgs)(cls);
【3】如上將func或cls重新賦值后,此時(shí)的func或cls也不再是原來定義時(shí)的func或cls,而是一個(gè)可執(zhí)行體,你只需要傳入?yún)?shù)就可調(diào)用,func(args)=>返回值或者輸出,cls(args)=>object of cls;
【4】最后通過賦值返回的執(zhí)行體是多樣的,可以是閉包,也可以是外部函數(shù);當(dāng)被裝飾的是一個(gè)類時(shí),還可以是類內(nèi)部方法,函數(shù);
【5】另外要想真正了解裝飾器,一定要了解func.func_code.co_varnames,func.func_defaults,通過它們你可以以func的定義之外,還原func的參數(shù)列表;另外關(guān)鍵字參數(shù)是因?yàn)檎{(diào)用而出現(xiàn)的,而不是因?yàn)閒unc的定義,func的定義中的用等號(hào)連接的只是有默認(rèn)值的參數(shù),它們并不一定會(huì)成為關(guān)鍵字參數(shù),因?yàn)槟闳匀豢梢园凑瘴恢脕韨鬟f它們。
新聞熱點(diǎn)
疑難解答
圖片精選