再看了很多装饰器代码解释之后,懵懂的我,突然顿悟。主要参考
http://pythonmap.iteye.com/blog/1682696
http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
其实这两个参考开始都看不下去。完全不懂呀。折磨时候,实验代码,随便折腾,竟然让我顿悟了。抓到精髓了,再看就简单了。还有个问题没有解决,就是装饰器的用处。主要参考http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 没理解下去。回头再看。
装饰器精髓:扮相 a,假演员 b,真演员 zhidou。 扮相必须且只能携带一个参数,用来接收假演员回传,真假演员必须带同个数参数。只能执行假演员规定动作。
某戏台要找出演《智斗》,演员要化妆成阿庆嫂的模样,那么就需要一个是准备阿庆嫂的扮相,另一个是找演员。装饰器的精髓就是这个。
>>> def a(m): #这个a就是阿庆嫂的扮相,这里的参数m就是传入的真演员。
... print "hello" #迷惑敌人
... def b(): #假设演员是 b
... return "A Qing Sao"#这个是演员在这部戏里面需要做的事情
... print "world" #迷惑敌人
... return b #这个 b 就是演员,把 b 塞到 a 的扮相下
...
#上面就定义好了阿庆嫂的扮相和演员要做的事情
>>> @a #这个表示下面出场的是阿庆嫂
... def zhidou(): #出演的演员名字是zhidou()
... print "Diao De Yi" #迷惑敌人
... return "Sha Jia Bang" #迷惑敌人
...
hello #迷惑敌人
world #迷惑敌人
>>> zhidou() #大幕拉开,演员zhidou已经化好妆上台,开始表演了
'A Qing Sao' #看到了吧,输出只有规定好的动作,其他的都是浮云。
分析上面的代码,其中“迷惑敌人”的部分不用理,去掉,剩下的精髓就是阿庆嫂的扮相 a 和假定的演员 b 以及最后出演的真实的演员 zhidou 这三个部分。
其中扮相 a 必须携带一个参数,而且只能携带一个参数,这个参数是用来接收最后假定的演员 b ,在扮相 a 的面具下塞入 b。
还要有一个真实演员 zhidou,这就行了。简化代码。 而真正演员要做的事情,就是b里面规定的内容,其他地方无论是什么都是在开演前迷惑观众,宣传造势用的。
真正开演了,就做一件事情,就是b里面规定的事情。
def a(m): #阿庆嫂扮相
def b(): pass #演员要做的事情
return b #把 b 塞到 阿庆嫂的扮相下
@a #按照 a 的标准打扮的说明文字
def zhidou(): pass #真演员开始化妆
zhidou() #真演员开演
上面举例是演员 b 不带参数的,那么真演员 zhidou 也要不带参数。
如果 b 带着参数,那么 zhidou 也要带相同的参数
这样才可以演嘛。
但是无论怎么变, 扮相 a 里面只能带一个参数,而且只能带一个,返回值,也必须是这个假演员。
那么这个装饰器的作用是什么呢? 目前看是可以按不同扮相打扮真演员。
比如
@a
@A
def zhidou():pass
也就是同时有几个扮相打扮真演员。
具体打扮成什么样就看实际应用了。这里只是一个理解。
下面是带参的模样。迷惑部分就不写了,只写有用部分。可以带几个参数,现在设置只带一个参数。还可以b(x,y)等等。
def a(m):
def b(x): return x+x
return b
@a
def zhidou(y): return "hello"
zhidou(3) #运行结果就是一个6,没有输出任何“hello”。 这里又加了一个迷惑部分“hello”,只是为了更清楚,这不部分,无论写成什么,都不会起作用。
所以,请记住,装饰器的三大组成,扮相,假演员,真演员。 扮相必须带参数,用来接收假演员返回。真假演员必须佩带相同的参数。
还是挺高兴的。编程时候记住三个词,扮相、假演员、真演员。其他的就随手拈来。理解了精髓,可以看别人代码,慢慢学习。
附上 阿庆嫂 扮相一张,振奋一下昏昏欲睡的下午精神。
但是注意的是,上面例子中的真演员的动作忽略没有执行。那么如何执行真演员的动作呢?第二个精髓:装饰器只能执行假演员规定动作。扮相携带的参数,就是真演员函数,因为只能执行假演员规定的动作,所以要把真演员函数放到假演员函数中执行。
又经过了学习,参考了www.2cto.com/kf/201410/345585.html/将装饰器实际应用结合理解如下:
上面的扮相,真假演员的理解中,真演员规定的动作并没有执行,只是执行了假演员执行的动作。那么现在要加进去真演员的动作。
def a(m):
def b(x,y):
print "hello",m(x,y) #这里把真演员的动作调入
return b
@a
def k(x,y):
return “%s wolaile %s” % (x,y)
运行 k("xiaoq","world") 结果为 hello xiaoq wolaile world 这样就将真假演员的动作都合在一起了。这样的 a 扮相叫做装饰器,借用设计假演员的动作,包装真演员。同时还不遗漏真演员的动作。这样真演员中的函数部分就不是迷惑敌人的用处,就可以使用了。
所以现在可以学着使用装饰器。一个场合是给真演员加点附加的运算。主要设计是放在b里面
举例
>>> class C(object): ... def __init__(self,x,y): ... self.name=x ... self.language=y ... def show(self): ... print self.name,"+++",self.language ## 上面定义了一个类 C >>> def a(m): ... def b(x,y): ... kk=m(x,y) #运行了真演员的动作,获取返回信息 ... print "hello",kk[0],kk[1] #设计真演员动作 ... return b ... >>> @a ... def k(x,y): #真演员动作 ... c=C(x,y) ... return c.name,c.language #把信息返回供扮相 a 设计。 ... >>> k("xiaoq","China") hello xiaoq China #记住一点,运行的一定只有 b 里面规定的内容,其他都是浮云。
好了,现在真假演员如何包装的已经看懂了,应用也了解了,可以去看别人代码了。 记住一点,扮相带参,真假演员,执行的是指假演员规定的动作。
注意装饰器和内建嵌套函数的区别。 内建嵌套函数不常用,外建嵌套函数常用,其实单独定义一个函数A,然后在定义另外一个函数B的时候,使用这个函数A而已。
python多用类函数,模块函数。很少使用自定义的内建嵌套函数。基本没有。所以这里注意和内建嵌套函数区分开。
但是有一种嵌套函数的闭包特性 http://www.jb51.net/article/55533.htm
>>> def test(): ... a={'name':'wyj'} ... def f(): ... return a['name'] ... return a,f ... >>> a,f =test() >>> f() 'wyj' >>> a {'name': 'wyj'} >>> a['name']='weklj' #指定了a的修改 >>> f() #f的值也跟着改了。 好奇怪。这里需要研究一下。待定。 'weklj' #想象中,也许,a和f在赋值test()的时候就已经按照test的规则规定了它们的关系,潜藏着某种运算规则,
所以,a改了,f也随着改了。从赋值 a,f=test() 开始,就决定了a和f之间的某个法则,就是test规定的内容。