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-17 20:13:50 +08:00 · 1559 次点击
    这是一个创建于 2716 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class MyType(type):
    def __init__(self, what, bases=None, dict=None):
    print('call myType.__init__()') #语句 1
    super().__init__(what, bases, dict)

    def __new__(cls, name, bases, attrs):
    print("call MyType.__new__()") #语句 2
    return type.__new__(cls, name, bases, attrs)

    def __call__(self, *args, **kwargs):
    print("MyType.__call__")

    class Foo(object, metaclass=MyType):
    def __init__(self, name=None):
    self.name = name
    print("Foo self.name=", self.name)

    def __new__(cls, *args, **kwargs):
    print("Foo.__new__ cls=", cls)
    return(object.__new__(cls, *args, **kwargs))

    def __call__(self, cls):
    print("Foo.__call__ cls=", cls)


    if __name__ == '__main__':
    print("---------test---------") #语句 3
    obj=Foo() #语句 4



    上面代码在 PYTHON3.6 中输出如下:
    call MyType.__new__() #语句 2 的输出
    call myType.__init__() #语句 1 的输出
    ---------test---------
    MyType.__call__ #语句 4 的输出


    我的问题如下:
    1、当 PYTHON 加载模块的时候,是否就会自动执行类定义中的 __init__和__new__方法,以此实现为类分配内存的目的?
    2、为何语句 4 “ obj=Foo()” 会导致__call__方法的执行?
    我看了一些博文,都提到“对象=类名()”这样的语句是不应该导致__call__执行的,只有“对象()”以及“类名()()”这两种语句才会触发__call__,
    上面语句 4 的输出是怎么回事呢?

    感谢指点!
    4 条回复    2017-07-18 21:37:22 +08:00
    saximi
        1
    saximi  
    OP
       2017-07-17 20:16:37 +08:00
    顺便问一下,为何我在外面编辑好的代码包含了缩进,一贴到论坛里就体现不出缩进了?
    bravecarrot
        2
    bravecarrot  
       2017-07-18 01:18:14 +08:00 via iPhone
    附加问题:你需要使用 markdown,代码块儿是''' 1⃣️那个键位。
    1. 先调用__new__。但是很少有人这么写,因为一般都用不到。参见 stackoverflow 上关于 new 的问题。然后调用 init。是不是分配内存,我没研究过,不妄言
    2.obj=Foo()==Foo.__call__()
    NoAnyLove
        3
    NoAnyLove  
       2017-07-18 10:29:51 +08:00
    要用 Markdown 格式包围代码才能保证缩进,而且仅对发帖有效,回帖不支持 Markdown
    saximi
        4
    saximi  
    OP
       2017-07-18 21:37:22 +08:00
    @bravecarrot 感谢,但是我越发糊涂了。
    我看了这篇博文 http://python.jobbole.com/83747/
    博文的“ 5.__call__”小节写了这段话:“注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()()”

    就是因为看了这段话,结合这个程序,我才觉得有问题,obj=Foo()这个语句应该是博文中的 对象=类名() 这个形式,所以不应该调用 Foo.__call__()方法才对啊?
    关于这个观点,我还有一个例子可以说明,比如下面这段代码和对应的输出,请注意语句 1 就是一个把对象实例化的语句,这个语句并没有调用类的__call__()方法:

    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()
    deco=Deco(mycls.myFunc) #语句 1

    代码输出如下:
    __init__执行完毕。func= <function MyCls.myFunc at 0x01C49AE0>
    __init__执行完毕。func= <__main__.Deco object at 0x01C4B190>
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3608 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:25 · PVG 12:25 · LAX 20:25 · JFK 23:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.