Python构造函数和__init__


107

为什么构造函数确实称为“构造函数”?它们的目的是什么?它们与类中的方法有何不同?

另外,__init__一个班级中可以有更多人吗?我尝试了以下方法,有人可以解释一下结果吗?

>>> class test:
    def __init__(self):
        print "init 1"
    def __init__(self):
        print "init 2"

>>> s=test()
init 2

最后,是__init__运算符重载器吗?


41
从技术上讲,__init__是一个初始化程序。python的构造函数__new__。Python使用自动两阶段初始化- __new__返回一个有效但(通常)未填充的对象(请参阅参考资料bool),然后__init__自动对其进行调用。这样可以避免像C ++这样的语言具有部分构造的对象的问题-在Python中您永远都不会遇到这样的问题(尽管它可能是部分初始化的)。你几乎从来不会需要同时重写__new____init__上一类。
Tim Delaney 2012年

2
@TimDelaney:我不确定您对C ++中的部分构造对象的含义。
塞巴斯蒂安·马赫2014年

11
@phresnel在C ++中,对象的类型是基类构造函数中的基类(而不是子类)。您不能在基类构造函数中调用虚拟方法,而必须由子类提供实现。在Java中,您可以在基类构造函数中调用子类方法,但是子类成员变量将在基类构造函数(和方法调用)之后自动初始化。在具有两阶段初始化的语言(如Python)中,您可以在基类初始化器中愉快地调用方法,并使子类提供(或覆盖)行为。
Tim Delaney 2014年

@TimDelaney:啊,谢谢你的澄清。
塞巴斯蒂安·马赫2014年

4
@TimDelaney。我认为您的评论应取代已接受的答案。
弗拉门戈

Answers:


114

Python中没有函数重载,这意味着您不能拥有多个具有相同名称但参数不同的函数。

在您的代码示例中,您没有过载 __init__()。发生的是第二个定义将名称重新绑定__init__到新方法,导致第一个方法不可访问。

至于关于构造函数的一般问题,维基百科是一个很好的起点。对于特定于Python的内容,我强烈推荐Python文档


这是否还意味着源文件是按顺序解析(解释)的?我可以确定以后定义的任何函数都可以覆盖先前定义的同名函数吗?:(我的Q听起来很傻..应该知道它
0xc0de 2012年

4
@ 0xc0de:在Python中,函数定义实际上是可执行语句,并且自上而下运行,所以是的。
NPE 2012年

1
@ 0xc0de实际上发生的是,类的主体在其自己的名称空间中执行,然后将该名称空间传递给元类(包括名称和基数)。然后,函数定义只是使用指定的主体创建函数并将其分配给它的名称。最后一个作业__init__将是该班级的作业。
2015年

64

为什么构造函数确实称为“构造函数”?

构造函数(名为__new__)创建并返回该类的新实例。因此,C.__new__类方法是类C 的构造函数

C.__init__创建特定实例后,将在特定实例上调用该实例方法,以对其进行初始化,然后再传递回调用方。因此,该方法是C的新实例的初始化程序

它们与类中的方法有何不同?

官方文档 __init__所述,实例创建后即被调用。其他方法不接受这种治疗。

他们的目的是什么?

构造函数的目的C.__new__是在构造新C实例期间定义自定义行为。

初始化程序的目的是为创建后C.__init__的每个实例定义自定义初始化C

例如,Python允许您执行以下操作:

class Test(object):
    pass

t = Test()

t.x = 10   # here you're building your object t
print t.x

但是,如果您希望每个实例Test的属性都x等于10,则可以将该代码放入其中__init__

class Test(object):
    def __init__(self):
        self.x = 10

t = Test()
print t.x

每个实例方法(在类的特定实例上调用的方法)都会将该实例作为其第一个参数。该论点通常命名为self

诸如构造方法之类的类方法将__new__接收类作为其第一个参数。

现在,如果您想要x属性的自定义值,您要做的就是将该值作为参数传递给__init__

class Test(object):
    def __init__(self, x):
        self.x = x

t = Test(10)
print t.x
z = Test(20)
print t.x

我希望这会帮助您清除一些疑问,并且由于您已经收到其他问题的良好答案,因此我将在这里停止:)


9

类只是从中创建对象的蓝图。构造函数是每次创建对象时都会运行的一些代码。因此,有两个构造函数是没有意义的。发生的是第二个覆盖了第一个。

通常将它们用作对象的创建变量,如下所示:

>>> class testing:
...     def __init__(self, init_value):
...         self.some_value = init_value

因此,您可以做的是从此类创建一个对象,如下所示:

>>> testobject = testing(5)

然后,testobject将有一个对象some_value,在该示例中该对象将为5。

>>> testobject.some_value
5

但是您不需要像我在示例中那样为每个对象设置值。您也可以这样:

>>> class testing:
...     def __init__(self):
...         self.some_value = 5

那么some_value的值将为5,并且在创建对象时无需设置它。

>>> testobject = testing()
>>> testobject.some_value
5

我的示例中的>>>和...不是您编写的。这就是在pyshell中的外观...


没问题,很高兴它对您有所帮助:)
Niclas Nilsson 2012年

1

创建新对象时会自动调用coonstructor,从而“构造”该对象。可以具有多个init的原因是因为名称只是python中的引用,并且您可以随时更改每个变量引用的内容(因此可以进行动态类型输入)

def func(): #now func refers to an empty funcion
    pass
...
func=5      #now func refers to the number 5
def func():
    print "something"    #now func refers to a different function

在您的类定义中,它只保留下一个


0

Python中没有方法重载的概念。但是您可以通过指定可选参数和关键字参数来达到类似的效果

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.