__init__作为构造函数?

时间:2011-07-05 06:03:25

标签: python constructor initialization

Dive into Python -

  

这很诱人但不正确   称之为的构造函数   类。这很诱人,因为它看起来很棒   像一个构造函数(按照惯例,   __init__是为类定义的第一个方法,就像一个人一样(它是   在a中执行的第一段代码   新创建的类实例),   甚至听起来像一个(“初始”   肯定建议一个构造函数   性质)。不正确,因为对象   已经建成了   时间__init__被召唤,而你   已经有了有效的参考资料   该课程的新实例。

引用表明将__init__作为构造函数调用是不正确的,因为该对象已在调用__init__时构建。但!我一直认为只有在构造对象之后才调用构造函数,因为它主要用于初始化实例的数据成员,如果对象没有这样做则没有意义在构造函数被调用时存在? (来自C ++ / Java背景)

6 个答案:

答案 0 :(得分:35)

如果你有一个班级Foo,那么:

  • Foo()构造函数
  • Foo.__init__()初始值设定项
  • Foo.__new__()分配器

构建Python对象只是分配一个新实例,然后初始化所述实例。

答案 1 :(得分:31)

就我个人而言,我发现“__init__不是构造函数”,可以很好地分解头发。

请求新对象时调用

__init__。它应该使用其参数来为新对象分配属性,以便设置对象正常操作所需的不变量。在__init__中的代码开始运行时,该对象已经是存储属性的有效预先存在的位置。 __init__中的代码开始运行时,新对象通常没有定义任何属性(除了所有对象都拥有的代码)。

在请求新对象时调用C ++构造函数。它应该使用其参数来分配新对象上的字段,以便设置对象正常操作所需的不变量。在构造函数中的代码开始运行时,该对象已经是存储字段的有效预先存在的位置。 当构造函数中的代码开始运行时,新对象已经包含了所有已声明的字段,但它们包含垃圾。

请求新对象时调用Java构造函数。它应该使用其参数来分配新对象上的字段,以便设置对象正常操作所需的不变量。在构造函数中的代码开始运行时,该对象已经是存储字段的有效预先存在的位置。 当构造函数中的代码开始运行时,新对象已经具有所有声明的字段,并带有默认值。

__init__方法和C ++ / Java构造函数之间的主要区别在于我突出显示的最后一句话,这就是Java / C ++的静态特性与Python的动态特性之间的区别。我认为这并不意味着要将它们称为根本不同的概念,而这些概念不应该被同一个词所引用。

我认为Pythonistas不喜欢将__init__称为构造函数的主要原因是人们认为的C ++ / Java构造函数是“创建一个新对象”,因为那是当你打电话给他们时他们似乎做了什么。但是当你调用一个构造函数时,真的会发生两件事;创建一个新对象,然后调用构造函数初始化它。在C ++ / Java中,“创建新对象”的一部分是不可见的,而这可以在Python中公开/自定义(通过__new__方法)。

因此虽然__init__方法的角色与C ++ / Java构造函数的角色非常相似,但是有些人更喜欢强调这不是整个过程的事实,而是说{{1}不是构造函数“。

答案 2 :(得分:5)

构造函数返回实例,可能会失败。但__init__不返回实例。即使__init__引发异常,也会调用__del__来删除实例。

这可以在这里看到:

class A(object):
    def __init__(self):
        raise ValueError

    def __del__(self):
        print "Called"

def main():
    try:
        a = A()
    except ValueError, e:
        print "ValueError"

if __name__ == '__main__':
    main()
另一方面,

__new__返回一个实例。

答案 3 :(得分:2)

来自http://www.programiz.com/article/python-self-why

  

__init__()不是构造函数

     

[..]一个重要的结论是[...],__init__()不是构造函数。许多天真的Python程序员都对它感到困惑,因为在创建对象时会调用__init__()。仔细观察将发现__init__()中的第一个参数是对象本身(对象已经存在)。函数__init__()在创建对象后立即调用,并用于初始化它。

     

从技术上讲,构造函数是一种创建对象本身的方法。在Python中,此方法为__new__()。这种方法的共同特征是

     

__new__(cls, *args, **kwargs)

关于Ben给出的回答,我会在这里争辩说,大多数语言都不会完全遵循这个定义。

此外:

  

调用__new__()时,类本身将自动作为第一个参数传递。这就是上述签名中cls的用途。同样,与self一样,cls只是一个命名约定。此外,*args**kwargs用于在Python中进行方法调用期间获取任意数量的参数。

     

实施__new__()时要记住的一些重要事项是:

     
      始终在__new__()之前调用
  1. __init__()
  2.   
  3. 第一个参数是隐式传递的类本身。
  4.   
  5. 始终从__new__()返回有效对象。不是强制性的,但这就是重点。
  6.   

Bottomline(对我而言):__new__()似乎是构造函数,而不是__init__(),尽管所有实际意义上__init__()都是大多数人认为构造函数会做的事情的一部分。

答案 4 :(得分:0)

John Zelle撰写的“编程Python:计算机科学概论”中说, “特殊方法__init__是对象构造函数 .Python调用此方法初始化一个新对象。__init__的作用是为实例变量提供初始值。对象“。

答案 5 :(得分:-6)

__init__不是构造函数,但是由于您在学习Python时对您无关紧要的原因。它的行为方式与您习惯于在C ++和Java中运行的构造函数一样。