[英]Python overriding __init__
I know that plenty of people ask questions on this subject, but I haven't seen my specific one asked. 我知道有很多人就这个问题提出问题,但我没有看到我的具体问题。 When subclassing you can override
__init__()
the same way that you can override any other method. 子类化时,您可以覆盖
__init__()
,就像覆盖任何其他方法一样。 My question is why in the example below this doesn't seem to be working correctly: 我的问题是为什么在下面的例子中这似乎没有正常工作:
import random
class MyRand(random.Random):
def __init__(self, myvar1, myvar2, x=None):
# ( ... my code ...)
super(MyRand, self).__init__(x)
Remember that Random
's constructor has the following signature: __init__(self, x=None)
where x
is an optional seed. 请记住,
Random
的构造函数具有以下签名: __init__(self, x=None)
其中x
是可选种子。 I want to keep that feature in my subclass, but also I want to require two mandatory variables, myvar1
and myvar2
. 我想在我的子类中保留该功能,但我还想要两个必需变量
myvar1
和myvar2
。
However, when you try and instantiate (without a seed) you get an error: 但是,当您尝试实例化(没有种子)时会出现错误:
MyRand('var1', 'var2')
TypeError: seed expected at most 1 arguments, got 2
This is because python thinks you want Random
's constructor and passes your two arguments 'var1' and 'var2' as the seed. 这是因为python认为你想要
Random
的构造函数并将你的两个参数'var1'和'var2'作为种子传递。 The seed (which is called from inside Random
's constructor) only wants 1 argument, and so you get an error. 种子(从
Random
的构造函数中调用)只需要1个参数,因此会出错。
However, if you do 但是,如果你这样做
MyRand(myvar1='var1', myvar2='var2')
This works, here python understands that you're passing it your two mandatory variables and not passing it the optional seed. 这是有效的,这里python知道你传递它的两个必需变量而不传递可选种子。
But I think the first case should work too. 但我认为第一种情况也应该奏效。 What's going on?
这是怎么回事?
In Python two methods are called when a object is created. 在Python中,在创建对象时会调用两个方法。
__new__
and __init__
. __new__
和__init__
。 Like many classes implemented in C, random.Random
uses __new__
to initialize itself (see random_new ). 像在C中实现的许多类一样,
random.Random
使用__new__
来初始化自己(参见random_new )。 You have to overwrite it and call it with the appropriate parameters: 您必须覆盖它并使用适当的参数调用它:
import random
class MyRand(random.Random):
def __new__(cls, myvar1, myvar2, x=None):
return random.Random.__new__(cls, x)
def __init__(self, myvar1, myvar2, x=None):
# ( ... my code ...)
You've mis-diagnosed the problem a little. 你错误地诊断了这个问题。 The problem is that
random.Random
's initialization isn't entirely contained in random.Random.__init__
. 问题是
random.Random
的初始化并不完全包含在random.Random.__init__
。 It also inherits _random.Random.__new__
: 它还继承了
_random.Random.__new__
:
static PyObject *
random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
RandomObject *self;
PyObject *tmp;
if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds))
return NULL;
self = (RandomObject *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
tmp = random_seed(self, args);
if (tmp == NULL) {
Py_DECREF(self);
return NULL;
}
Py_DECREF(tmp);
return (PyObject *)self;
}
You're going to have to override __new__
, too, and only pass the seed
argument it expects, positionally (because it doesn't understand it as a keyword argument). 您将不得不重写
__new__
,并且仅在位置上传递它期望的seed
参数(因为它不将其理解为关键字参数)。
They really shouldn't be mixing __init__
and __new__
like this. 他们真的不应该像这样混合
__init__
和__new__
。 Initialization order gets really weird when you do that. 当你这样做时,初始化顺序变得非常奇怪。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.