我正在覆盖类的__new__()
方法,以返回具有特定__init__()
集的类实例。 Python似乎调用类提供的__init__()
方法而不是特定于实例的方法,尽管
http://docs.python.org/reference/datamodel.html
表示:
典型的实现通过调用来创建类的新实例 superclass的__new __()方法使用super(currentclass,cls).__ new __(cls [,...]) 使用适当的参数,然后将新创建的实例修改为 在返回之前必要的。
如果__new __()返回cls的实例,那么新实例的__init __()方法 将像__init __(self [,...])一样被调用,其中self是新实例和 剩下的参数与传递给__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()
输出
$ python --version
Python 2.6.6
$ ./mytest.py
myclass.__init__ called, self.__init__ is <bound method myclass.myinit of <__main__.myclass object at 0x7fa72155c790>>
myinit called, args = (), kwargs = {}
似乎让myinit()
运行的唯一方法是在self.__init__()
内明确将其称为myclass.__init__()
。
答案 0 :(得分:9)
在实例的类型上查找新样式类的特殊方法,而不是实例本身。这是documented behaviour:
对于新式类,只有在对象的类型上定义特殊方法的隐式调用才能保证正常工作,而不是在对象的实例字典中。这种行为是以下代码引发异常的原因(与旧式类的等效示例不同):
>>> 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()
答案 1 :(得分:8)
各种特殊方法(包括__init__
,还有__add__
等运算符重载)都是always accessed via the class rather than the instance。不仅如此,它们无法通过类或元类的__getattr__
或__getattribute__
方法访问,它们必须直接在类上。这是出于效率的原因:
以这种方式绕过
__getattribute__()
机制为解释器内的速度优化提供了很大的空间,代价是处理特殊方法的一些灵活性(必须在类对象本身上按顺序设置特殊方法由翻译一致地调用。)
您要完成的目标并不完全清楚,但您可以做的一件事是在myclass
方法中继承__new__
:
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)
答案 2 :(得分:0)
为什么Python在实例创建时不调用实例方法 init (),而是调用类提供的 init ()?
查看此示例。
class C:
one = 42
def __init__(self,val):
self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)
结果将是这样的:
{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
请注意,只有值{'two': 50}
是实例字典的一部分。
'one': 42
属于类C
字典。 __init__
方法也是如此。
这是根据设计。