关于装饰器的问题请教,谢谢大家

2017-07-05 19:44:01 +08:00
 saximi
class Deco:
def __init__(self,func):
self.func=func
print("__init__执行完毕。func=",self.func)
def __call__(self,*arg,**arg2):
print("开始执行__call__。")
self.func('abc')
print(self,arg,arg2)

class MyCls():
@Deco
def myFunc(self):
print('this is my work arg is %s'%self)

mycls=MyCls() #语句 1
print("mycls=MyCls()执行完毕")
deco=Deco(mycls.myFunc) #语句 2
print("deco=Deco(mycls.myFunc)执行完毕")
deco(sendarg='abcdefg') #语句 3


上面这段代码的输出如下,前面的序号是我另外加上的:

1. __init__执行完毕。func=
2. mycls=MyCls()执行完毕
3. __init__执行完毕。func= <__main__.Deco object at 0x0208A110>
4. deco=Deco(mycls.myFunc)执行完毕
5. 开始执行__call__。
6. 开始执行__call__。
7. this is my work arg is abc
8. <__main__.Deco object at 0x0208A110> ('abc',) {}
9. <__main__.Deco object at 0x0208A150> () {'sendarg': 'abcdefg'}


对于上面的输出,我有以下问题:
1、为什么语句 1 会导致序号 1 的输出?
2、语句 2 是把类 Deco 实例化的操作,语句 3 产生了序号 3 的输出,为何实例化时只执行了类 Deco 的__init__函数而不执行__call__函数呢,难道不需要调用__call__来返回一个对象么?
3、语句 3 产生了序号 5 至序号 6 的 5 条输出内容,不明白为何是这样的输出顺序,恳请大家详细指点一下?

都是些小白问题,恳请大家不吝赐教,感谢!
1286 次点击
所在节点    Python
3 条回复
julyclyde
2017-07-06 10:04:38 +08:00
1 所谓生成一个 MyCls 的实例,就是把该 class 的定义语句执行一遍啊
2 实例化的时候当然不执行__call__啊!这东西是“把 class 当作 function 调用”的时候才执行的

建议你不要把面向对象、装饰器、__class__三者混在一起学
saximi
2017-07-07 21:12:48 +08:00
装饰器是在导入模块时立即执行的,所以装饰函数中的代码在导入模块时会被执行,
但是装饰函数中如果有__init__或__call__模块,这些模块中的代码在导入时是不会被执行的。

我按照上面这个说法来理解对不对呢?
carlonelong
2017-07-10 00:19:42 +08:00
这些函数都是有特殊含义的,你要学习建议先用自己定义的函数。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/373299

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX