关于python:__ init__作为构造函数?

__init__ as a constructor?

潜入Python-

It would be tempting but incorrect to
call this the constructor of the
class. It's tempting, because it looks
like a constructor (by convention,
__init__ is the first method defined for the class), acts like one (it's
the first piece of code executed in a
newly created instance of the class),
and even sounds like one ("init"
certainly suggests a constructor-ish
nature). Incorrect, because the object
has already been constructed by the
time __init__ is called, and you
already have a valid reference to the
new instance of the class.

引号表明将__init__作为构造函数调用是不正确的,因为对象已经在调用__init__时构造。但是!我一直认为只有在构造对象之后才调用构造函数,因为它本质上是用来初始化实例的数据成员的,如果在调用构造函数之前对象不存在,这是没有意义的?(来自C++/Java后台)


如果您有一个类Foo,那么:

  • Foo()为施工单位
  • Foo.__init__()是初始值设定项
  • Foo.__new__()是分配器
  • 小精灵

    python对象的构造只是分配一个新实例,然后初始化该实例。


    就我个人而言,我发现"__init__不是一个建设者",这是一个相当精细的发型。

    请求新对象时调用__init__。它应该使用自己的参数为新对象分配属性,这样就可以设置对象正常操作所需的不变量。当__init__中的代码开始运行时,对象已经是一个有效的预先存在的存储属性的地方。当__init__中的代码开始运行时,新对象通常没有在其上定义任何属性(所有对象都拥有的属性除外)。

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

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

    EDCOX1的4种方法和C++/Java构造函数的主要区别在于我已经强调的最后一句话,这只是爪哇/C++的静态性质和Python的动态性质之间的区别。我认为这并不意味着要称它们为根本不同的概念,而不能用同一个词来指代它们。

    我认为PythOnistas不喜欢引用EDCOX1 4作为构造函数的主要原因是人们认为C++ + Java构造函数是"创建一个新对象",因为这是他们在调用它们时所做的。但是当您调用一个构造函数时,实际上发生了两件事:创建一个新对象,然后调用该构造函数来初始化它。在C++/Java中,"创建一个新对象"的一部分是不可见的,而可以在Python中(通过EDCOX1×8的方法)进行曝光/定制。

    因此,尽管EDCOX1 4的方法的作用与C++/Java构造函数的作用极为相似,但有些人倾向于强调这不是整个过程,而是说"EDCOX1×4是不是一个构造函数"。


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

    这里可以看到:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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__返回一个实例。


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

    __init__() is not a constructor

    [..]One important conclusion [..] is that, __init__() is not a constructor. Many naive Python programmers get confused with it since __init__() gets called when we create an object. A closer inspection will reveal that the first parameter in __init__() is the object itself (object already exists). The function __init__() is called immediately after the object is created and is used to initialize it.

    Technically speaking, constructor is a method which creates the object itself. In Python, this method is __new__(). A common signature of this method is

    __new__(cls, *args, **kwargs)

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

    此外:

    When __new__() is called, the class itself is passed as the first argument automatically. This is what the cls in above signature is for. Again, like self, cls is just a naming convention. Furthermore, *args and **kwargs are used to take arbitary number of arguments during method calls in Python.

    Some important things to remember when implementing __new__() are:

  • __new__() is always called before __init__().
  • First argument is the class itself which is passed implicitly.
  • Always return a valid object from __new__(). Not mandatory, but thats the whole point.
  • 底线(对我来说):__new__()似乎是一个建设者,而不是__init__(),尽管从所有实际的角度来看,__init__()是大多数人认为建设者将要做的事情的一部分。


    约翰·泽尔在《编程Python:计算机科学导论》中说,"特殊方法__init__是对象构造函数。python调用这个方法来初始化一个新对象。__init__的作用是为对象的实例变量提供初始值。"


    __init__不是一个构造函数,而是因为在学习Python的过程中这些原因对您来说并不重要。它的行为方式是用在C++和Java中的构造函数。