Python的(和Python C API):__new__与__init__ [英] Python (and Python C API): __new__ versus __init__

查看:209
本文介绍了Python的(和Python C API):__new__与__init__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要问的问题似乎是 Python的使用__new__和__init__?,但无论如何,它仍然不清楚我到底是什么之间的 __新__ __的init __

The question I'm about to ask seems to be a duplicate of Python's use of __new__ and __init__?, but regardless, it's still unclear to me exactly what the practical difference between __new__ and __init__ is.

在你匆匆地告诉我, __新__ 是用于创建对象和 __的init __ 是初始化对象,让我明确:我得到其实,这样的区分是很自然的我,因为我有在C ++中的经验,我们有的安置新,这同样对象分配从初始化分开。

Before you rush to tell me that __new__ is for creating objects and __init__ is for initializing objects, let me be clear: I get that. In fact, that distinction is quite natural to me, since I have experience in C++ where we have placement new, which similarly separates object allocation from initialization.

借助 Python的C API教程解释它是这样的:

新的成员负责
  创建(相对于初始化)
  的类型的对象。它是在暴露
  Python作为在 __ __新()方法。 ...
  以实施新的方法的原因之一是保证的初始值
  实例变量

The new member is responsible for creating (as opposed to initializing) objects of the type. It is exposed in Python as the __new__() method. ... One reason to implement a new method is to assure the initial values of instance variables.

所以,是的 - 我的 GET 的东西 __新__ 确实,但尽管这样,我的还是的不明白为什么它在Python是非常有用的。给出的例子说, __ __新,如果你想确保实例变量的初始值可能是有用的。那么,是不是说什么 __ __的init 会做什么?

So, yeah - I get what __new__ does, but despite this, I still don't understand why it's useful in Python. The example given says that __new__ might be useful if you want to "assure the initial values of instance variables". Well, isn't that exactly what __init__ will do?

在C API教程,显示一个例子,其中创建了一个新的类型(称为诺迪),以及该类型的 __新__ 函数的定义。诺迪类型包含名为第一字符串成员,这个字符串成员被初始化到像这样一个空字符串:

In the C API tutorial, an example is shown where a new Type (called a "Noddy") is created, and the Type's __new__ function is defined. The Noddy type contains a string member called first, and this string member is initialized to an empty string like so:

static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    .....

    self->first = PyString_FromString("");
    if (self->first == NULL)
    {
       Py_DECREF(self);
       return NULL;
    }

    .....
}

请注意,如果没有 __新__ 方法在这里定义的,我们不得不使用 PyType_GenericNew ,它只是初始化所有实例变量的成员为NULL。因此,的__新的唯一好处__ 方法是实例变量将开始作为一个空字符串,而不是NULL。 但是,为什么是这个不断有用的,因为如果我们关心确保我们的实例变量初始化为一些默认值,我们可以只做到这一点在 __的init __ 方法?

Note that without the __new__ method defined here, we'd have to use PyType_GenericNew, which simply initializes all of the instance variable members to NULL. So the only benefit of the __new__ method is that the instance variable will start out as an empty string, as opposed to NULL. But why is this ever useful, since if we cared about making sure our instance variables are initialized to some default value, we could have just done that in the __init__ method?

推荐答案

的差异主要源自与可变VS不变类型。

The difference mainly arises with mutable vs immutable types.

__ __新接受的键入的作为第一个参数,和(通常)返回该类型的新实例。因此,它是适用于两种可变和不可变类型的使用。

__new__ accepts a type as the first argument, and (usually) returns a new instance of that type. Thus it is suitable for use with both mutable and immutable types.

__ __的init 接受一个的实例的作为第一个参数,并修改该实例的属性。这是不恰当的一个不变的类型,因为这将让他们在创建后进行修改,通过调用的obj .__的init __(*参数)

__init__ accepts an instance as the first argument and modifies the attributes of that instance. This is inappropriate for an immutable type, as it would allow them to be modified after creation by calling obj.__init__(*args).

比较行为的元组列表

>>> x = (1, 2)
>>> x
(1, 2)
>>> x.__init__([3, 4])
>>> x # tuple.__init__ does nothing
(1, 2)
>>> y = [1, 2]
>>> y
[1, 2]
>>> y.__init__([3, 4])
>>> y # list.__init__ reinitialises the object
[3, 4]

至于为什么他们(从简单的历史原因除外)分开: __新__ 方法需要一堆样板得到正确(初始对象创建,然后记住返回在结束对象)。 __ __的init 方法,相反,是死的简单,因为你只需设置你需要设置任何属性。

As to why they're separate (aside from simple historical reasons): __new__ methods require a bunch of boilerplate to get right (the initial object creation, and then remembering to return the object at the end). __init__ methods, by contrast, are dead simple, since you just set whatever attributes you need to set.

除了 __的init __ 是更容易编写和可变VS一成不变的区别上面提到的方法,分离还可以被利用来使调用父类 __ __的init 在子类中由__ __新设置任何绝对必要的情况下不变量可选。这通常是一个可疑的做法,但 - 它通常更清楚,只是调用父类 __ __的init 方法在必要

Aside from __init__ methods being easier to write, and the mutable vs immutable distinction noted above, the separation can also be exploited to make calling the parent class __init__ in subclasses optional by setting up any absolutely required instance invariants in __new__. This is generally a dubious practice though - it's usually clearer to just call the parent class __init__ methods as necessary.

这篇关于Python的(和Python C API):__new__与__init__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆