V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
saximi
V2EX  ›  Python

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

  •  
  •   saximi · 2017-07-05 19:44:01 +08:00 · 1359 次点击
    这是一个创建于 2724 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 条输出内容,不明白为何是这样的输出顺序,恳请大家详细指点一下?

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

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

    我按照上面这个说法来理解对不对呢?
    carlonelong
        3
    carlonelong  
       2017-07-10 00:19:42 +08:00
    这些函数都是有特殊含义的,你要学习建议先用自己定义的函数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1075 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 22:45 · PVG 06:45 · LAX 14:45 · JFK 17:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.