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 "<pyshell#224>", line 1, in <module>
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 0x0000000002C3E390>
> 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 0x0000000003AF7748>
> 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 0x0000000003AAFA20>
> 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 0x0000000003AAFA20>
> 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 0x0000000003AB50B8>
> 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 0x0000000003AB5588>
> 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,装饰器
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]