为什么Python在创建实例时不调用实例方法\uyu init_uu9(),而是调用类提供的yu init_uu9()?

2024-06-02 08:23:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我重写了一个类的__new__()方法,以返回一个具有特定__init__()集的类实例。Python似乎调用类提供的__init__()方法,而不是实例特定的方法,尽管Python文档位于

http://docs.python.org/reference/datamodel.html

说:

Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super(currentclass, cls).__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

这是我的测试代码:

#!/usr/bin/env python

import new

def myinit(self, *args, **kwargs):
    print "myinit called, args = %s, kwargs = %s" % (args, kwargs)


class myclass(object):
    def __new__(cls, *args, **kwargs):
        ret = object.__new__(cls)

        ret.__init__ = new.instancemethod(myinit, ret, cls)
        return ret

    def __init__(self, *args, **kwargs):
        print "myclass.__init__ called, self.__init__ is %s" % self.__init__
        self.__init__(*args, **kwargs)

a = myclass()

哪些输出

^{pr2}$

似乎让myinit()运行的唯一方法是在myclass.__init__()内显式地调用它self.__init__()。在


Tags: ofthe实例方法instanceselfnewinit
3条回答

新样式类上的特殊方法是在实例的类型上查找的,而不是在实例本身上查找的。这是documented behaviour

For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary. That behaviour is the reason why the following code raises an exception (unlike the equivalent example with old-style classes):

>>> class C(object):
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

Why doesn't Python call instance method init() on instance creation but calls class-provided init() instead?

看看这个例子。在

class C:
   one = 42
   def __init__(self,val):
        self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)

结果如下:

^{pr2}$

注意,只有值{'two': 50}是实例dict的一部分

'one': 42属于一个Cdict类。__init__方法也是如此。在

这是按设计的。在

各种特殊方法(包括__init__,但也有运算符重载,如__add__,等等)是always accessed via the class rather than the instance。不仅如此,而且不能通过类或元类上的__getattr__或{}方法访问它们,它们必须直接位于类上。这是为了提高效率:

Bypassing the __getattribute__() machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method must be set on the class object itself in order to be consistently invoked by the interpreter).

目前还不完全清楚您要实现什么目标,但您可以在这里做的一件事是在__new__方法中对myclass进行子类化:

class myclass(object):
    def __new__(cls, *args, **kwargs):
        class subcls(cls):
            def __new__(cls, *args, **kwargs):
                return object.__new__(cls)
        subcls.__init__ = myinit
        return subcls(*args, **kwargs)

相关问题 更多 >