__init__作为构造函数?

Vai*_*pai 40 python constructor initialization

潜入Python -

将它称为类的构造函数会很诱人但不正确.这很诱人,因为它看起来像构造函数(按照惯例, __init__是为类定义的第一个方法),就像一个(它是在新创建的类实例中执行的第一段代码),甚至听起来像一个( "init"肯定表明了构造函数的本质.不正确,因为调用时已经构造了对象__init__,并且您已经拥有对该类的新实例的有效引用.

报价表明,它是不正确调用__init__构造函数,因为该对象已建成的时候__init__被调用.但!我一直的印象是,在构造函数只调用构造对象之后,因为它本质上是使用,如果该对象未通过时存在来初始化实例,它是没有意义的数据成员的构造函数被调用?(来自C++/Java背景)

Ign*_*ams 35

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

  • Foo()构造函数
  • Foo.__init__()初始化器
  • Foo.__new__()分配器

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

  • 实际上,根据http://docs.python.org/reference/datamodel.html#basic-customization中使用的语言,`Foo()`是**构造函数表达式**,而`Foo .__ init__`是**构造函数**.(并且从相同的参考文献中,`__del__`也称为"析构函数";不使用术语终结符).这个"__init__"不能被称为构造函数的都市神话是完全错误的. (24认同)
  • 无论`__init__`是什么,我都不同意`Foo()`是一个构造函数.`Foo()`是对名为Foo的东西的调用.如果Foo是一个通常行为的类,这个调用将导致构造一个新对象,但这是通过调用`Foo()`而不是表达式'Foo()`本身来达到*的代码. (9认同)
  • @Vaibhav:终结者. (2认同)
  • @JosiahYoder 不,他们在某个时候更改了描述。它仍然存在于 Python 2.6 文档 (https://docs.python.org/2.6/reference/datamodel.html#basic-customization) 中,其中关于 __init__` 方法的部分说“作为构造函数的特殊约束,没有值可能会被返回”。 (2认同)

Ben*_*Ben 35

就个人而言,我发现" __init__不是一个构造函数"是非常精细的分裂.

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

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

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

__init__方法和C++/Java构造函数之间的主要区别在于我突出显示的最后一句话,这就是Java/C++的静态特性与Python的动态特性之间的区别.我不认为这保证称它们是根本不同的概念,不能用同一个词来指代.

我认为Pythonistas不喜欢将其__init__称为构造函数的主要原因是人们认为 C++/Java构造函数是"创建一个新对象",因为这就是他们在调用它们时所做的事情.但是当你调用一个构造函数时,真的会发生两件事; 创建一个新对象,然后调用构造函数初始化它.在C++/Java中,"创建新对象"的一部分是不可见的,而这可以在Python中公开/自定义(通过该__new__方法).

因此,尽管该__init__方法的作用与C++/Java构造函数的作用非常相似,但有些人更愿意通过说" __init__不是构造函数" 来强调这不是整个过程的事实.

  • 你指出的区别是一个参数调用`__init__` 一个构造函数甚至更多。毕竟,它比 C++/C#/Java 的构造函数做更多的“构造”(创建属性,而不仅仅是初始化它们)。 (2认同)

小智 6

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

__init__()不是构造函数

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

从技术上讲,构造函数是创建对象本身的方法。在Python中,这个方法是__new__(). 此方法的常见签名是

__new__(cls, *args, **kwargs)

关于本给出的答案,我在这里认为,大多数语言并不(完全)遵循该定义。

此外:

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

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

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

底线(对我来说):__new__()似乎是构造函数,尽管__init__()通过所有实际手段__init__()做了大多数人认为构造函数会做的部分事情。

  • 我可以理解这样的说法:“构造”应该是整个“分配一个新对象,然后初始化其属性”过程;调用 `SomeClass(1, 2, 3)` 所做的一切,而不仅仅是调用 `__init __`。但如果你想这么说,你**也**认为 Java 构造函数不应该被称为构造函数,因为它们在这个过程中所做的正是 __init__` 所做的事情。而且这个定义*仍然*最终没有合理的理由将`__new__`称为构造函数,因为它**也**只是整个构造过程的一部分。 (3认同)
  • 但是,当您编写 Java/C#/C++/任何 OO 语言的构造函数时,您编写的代码将在已存在的对象上调用,就像“__init__”(与“__new__”不同)。您编写的构造函数方法不会返回对象,它会通过写入其属性来修改它,然后停止,就像“__init__”(与“__new__”不同)。`__new__` 并不**执行构造函数在其他语言中所做的事情,它**在调用您编写的构造函数之前**执行语言系统为您所做的事情。 (2认同)

Rum*_*kin 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()
Run Code Online (Sandbox Code Playgroud)

__new__ 另一方面,返回一个实例。