Python (and Python C API): __new__ versus __init__
我将要问的问题似乎是python使用"new"和"init"的复制品。但不管怎样,我仍然不清楚
在你急着告诉我
python c api教程解释如下:
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.
号
所以,是的-我知道
在C API教程中,将显示一个示例,其中创建了一个新类型(称为"noddy"),并定义了该类型的
1 2 3 4 5 6 7 8 9 10 11 12 13 | static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ..... self->first = PyString_FromString(""); if (self->first == NULL) { Py_DECREF(self); return NULL; } ..... } |
注意,如果没有这里定义的
差异主要出现在可变类型和不可变类型之间。
比较
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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] |
至于为什么它们是分开的(除了简单的历史原因):
除了
1 2 3 4 | class ModularTuple(tuple): def __new__(cls, tup, size=100): tup = (int(x) % size for x in tup) return super(ModularTuple, cls).__new__(cls, tup) |
你不能用
1 2 3 4 5 6 7 8 9 | >>> class C(object): ... def __new__(cls): ... return 5 ... >>> c = C() >>> print type(c) <type 'int'> >>> print c 5 |
不是一个完整的答案,但可能是一些能说明差异的东西。
当必须创建对象时,将始终调用
只是想增加一个词来说明定义
当我试图理解定义一个类工厂的最佳方法时,我(和其他人)遇到了这个问题。我认识到,
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?
考虑到所述的场景,当实例实际上是类本身时,我们关心实例变量的初始值。因此,如果我们在运行时动态地创建一个类对象,并且我们需要定义/控制关于正在创建的这个类的后续实例的特殊内容,那么我们将在一个元类的
我对此感到困惑,直到我真正考虑到这个概念的应用,而不仅仅是它的意义。下面是一个很有希望使区别变得清晰的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | a = Shape(sides=3, base=2, height=12) b = Shape(sides=4, length=2) print(a.area()) print(b.area()) # I want `a` and `b` to be an instances of either of 'Square' or 'Triangle' # depending on number of sides and also the `.area()` method to do the right # thing. How do I do that without creating a Shape class with all the # methods having a bunch of `if`s ? Here is one possibility class Shape: def __new__(cls, sides, *args, **kwargs): if sides == 3: return Triangle(*args, **kwargs) else: return Square(*args, **kwargs) class Triangle: def __init__(self, base, height): self.base = base self.height = height def area(self): return (self.base * self.height) / 2 class Square: def __init__(self, length): self.length = length def area(self): return self.length*self.length |
注意,这只是一个示范性的例子。在不使用上述类工厂方法的情况下,有多种方法可以获得解决方案,即使我们确实选择以这种方式实现解决方案,但为了简洁起见,还有一点需要注意的地方(例如,显式声明元类)。
如果您正在创建一个常规类(也就是非元类),那么