你问的是两个经常混淆的话题:初始化器__init__
和构造器__new__
。另外,我认为您将 Python 与 Java 之类的语言混淆了,其中构造函数很重要,不像其他语言,构造和初始化混合在一个进程中(因此对于 Python 新手来说是一个常见的误解)。
在 Python 中,构造器和初始化器都是方法,与任何其他方法没有区别。有一个命名约定,解释器将调用两端带有双下划线的(某些)方法,而无需您显式地调用它们,但是如果您愿意,您可以自己调用它们,并且您会得到相同的结果。
简而言之:如果你理解__str__
,你就会理解__init__
和__new__
。
(我认为对于一些有经验的程序员来说,Python 最奇怪的地方在于它不会每时每刻都用特殊情况来伏击你。)
方法解析顺序
Python 2.3 的新型类通过从对象的类开始查找方法名称,然后遍历该类的祖先,直到找到要查找的名称或用完要搜索的类。
您可以通过查看其__mro__
字段来查看任何类的方法解析顺序:
>>> TestClass.__mro__
(<class '__main__.TestClass'>, <class 'object'>)
>>> float.__mro__
(<class 'float'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
(Python 使用C3 Method Resolution Order algorithm构造元组,但对于像你这样的简单案例来说,它是矫枉过正的。C3 主要关注将复杂的多重继承图线性化为可以按可预测顺序搜索的类元组。 )
任何方法查找,甚至__init__
或__new__
,都遵循方法解析顺序。对于元组中的每个类,Python'__init__'
在其类中查找字符串(如 )__dict__
;如果该字符串存在,则其关联值——无论它是什么——将作为方法查找的结果返回。
在您的情况下,Python 查找TestClass.__new__
, 不存在,然后object.__new__
, 存在。然后它会执行object.__new__
(自动填充一些参数)来构造你的新TestClass
对象。初始化__init__
是相同的,只是您可以自己提供一些额外的参数。
证明(在 Python 3 中):
>>> class A: pass
...
>>> A.__init__ is object.__init__
True
>>> A.__new__ is object.__new__
True
>>> A.__repr__ is object.__repr__
True
>>> A.__str__ is object.__str__
True
参数__init__
您尝试将参数传递给object.__init__
失败,因为该方法不接受任何参数(除了self
已经为您填写的参数)。它或多或少看起来像这样:
class Object:
def __init__(self):
return
结论
Python 不会像(IIRC)Java 那样为您的类“创建”默认构造函数或初始化程序。但它在课堂上各有一个object
,所以如果你不自己写,你会继承它们。