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-04 18:36:27 +08:00 · 1707 次点击
    这是一个创建于 2699 天前的主题,其中的信息可能已经有所发展或是发生改变。
    类实例化成对象时,首先应该是调用类中的__call__函数,在__call__函数中先用__new__方法为对象分配内存空间,然后再在__call__函数中调用__init__方法初始化对象。如果这么理解没错的话,是否可以自己来实现类中的__call__函数,达到覆盖默认函数的目的呢?
    但是我在网上看到这段说明以及相关代码的运行结果,觉得不理解,恳请指点!

    代码定义了 Foo 类,但又为 Foo 定义了一个 __call__方法,
    资料上说这时 Foo(*args, **kwargs) 实例化对象时并不等于 Foo.__call__(*args, **kwargs):

    >>> class Foo:
    ... def __call__(self):
    ... print('running __call__')
    ...

    >>> Foo()
    <__main__.Foo object at 0x000000000227ABE0>

    >>> Foo.__call__()
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: __call__() missing 1 required positional argument: 'self'
    In this case, __call__ is used to call instances of the class :

    >>> Foo()()
    running __call__
    4 条回复    2017-07-06 22:09:25 +08:00
    fffflyfish
        1
    fffflyfish  
       2017-07-04 20:55:56 +08:00
    类实例化成对象,不是首先应该调用构造函数吗,__call__是针对已经实例化的对象作为函数的时候用的吧
    ![屏幕快照 2017-07-04 下午 8.55.25.png]( https://ooo.0o0.ooo/2017/07/04/595b904e49327.png)
    tonychow
        2
    tonychow  
       2017-07-05 00:12:51 +08:00
    __call__(self[, args...]) 方法是实例方法而非类方法

    ref https://docs.python.org/2/reference/datamodel.html#emulating-callable-objects
    saximi
        3
    saximi  
    OP
       2017-07-05 19:42:20 +08:00
    @tonychow 谢谢,我是在 http://www.jianshu.com/p/f63ad9d550f1 这篇文章中看到对于常规类的实例化步骤描述为大致等同如下:

    def __call__(obj_type, *args, **kwargs):
    obj = obj_type.__new__(*args, **kwargs)
    if obj is not None and issubclass(obj, obj_type):
    obj.__init__(*args, **kwargs)
    return obj

    __new__方法为对象分配了内存空间,构建它为一个“空"对象然后__init__方法被调用来初始化它。总的来说:

    Foo(*args, **kwargs)等价于 Foo.__call__(*args, **kwargs)

    既然 Foo 是一个 type 的实例,Foo.__call__(*args, **kwargs)实际调用的是 type.__call__(Foo, *args, **kwargs)

    type.__call__(Foo, *args, **kwargs)调用 type.__new__(Foo, *args, **kwargs),然后返回一个对象。
    obj 随后通过调用 obj.__init__(*args, **kwargs)被初始化。
    obj 被返回。


    我帖子所提的问题也是这个网址在文章末尾提出的关注点,我就是不明白要怎么理解
    saximi
        4
    saximi  
    OP
       2017-07-06 22:09:25 +08:00
    自己顶一下,恳请大家指点,感谢啊!!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2651 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 11:52 · PVG 19:52 · LAX 03:52 · JFK 06:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.