Python重写初始化__
我知道很多人都会问这个问题,但我还没有看到有人问我的问题。当子类化时,可以重写Python重写初始化__,python,Python,我知道很多人都会问这个问题,但我还没有看到有人问我的问题。当子类化时,可以重写\uuuu init\uuu(),就像重写任何其他方法一样。我的问题是,为什么在下面的示例中,这似乎不能正常工作: import random class MyRand(random.Random): def __init__(self, myvar1, myvar2, x=None): # ( ... my code ...) super(MyRand, self).__ini
\uuuu init\uuu()
,就像重写任何其他方法一样。我的问题是,为什么在下面的示例中,这似乎不能正常工作:
import random
class MyRand(random.Random):
def __init__(self, myvar1, myvar2, x=None):
# ( ... my code ...)
super(MyRand, self).__init__(x)
请记住,Random
的构造函数具有以下签名:初始化(self,x=None)
其中x
是可选种子。我想在我的子类中保留该特性,但我还需要两个强制变量,myvar1
和myvar2
但是,当您尝试实例化(没有种子)时,会出现一个错误:
MyRand('var1', 'var2')
TypeError: seed expected at most 1 arguments, got 2
这是因为python认为您需要随机的构造函数,并将两个参数“var1”和“var2”作为种子传递。seed(从Random
的构造函数内部调用)只需要一个参数,因此您会得到一个错误
然而,如果你这样做
MyRand(myvar1='var1', myvar2='var2')
这是可行的,在这里python理解您将两个强制变量传递给它,而不是将可选种子传递给它
但我认为第一个案例也应该有效。发生了什么事?在Python中,创建对象时会调用两个方法<代码>\uuuuuuuuuuuuuuuuuuuuuuu和
\uuuuuuuu init\uuuuuuuuuuuuuuuuuu
。与C语言中实现的许多类一样,random.random
使用\uuuuu new\uuuuu
来初始化自身(请参阅)。您必须覆盖它并使用适当的参数调用它:
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 ...)
你有点误判了这个问题。问题是
random.random
的初始化并不完全包含在random.random.\uuuu init\uuuu
中。它还继承了:
您还必须重写\uuuuu new\uuuuu
,并且只按位置传递它所期望的种子
参数(因为它不将其理解为关键字参数)
他们真的不应该像这样把
\uuuuu init\uuuu
和\uuu new\uuuuu
混在一起。当你这样做的时候,初始化顺序会变得非常奇怪。super
在Python 3中没有任何必要的参数。@ADR:这在这个问题上既不重要也不重要。我不理解对这个问题的否决票……是的,我只是读了答案。我在继承Exception
时偶然发现了相同的行为。是时候仔细看看那些默默无闻的\uuuuuxxxx\uuuuuu
成员了。@Jean-Françoisfare你说的是真的,但不适用于这里。在我的示例代码中,我的\uuu init\uu
从未执行过,因此super
也没有执行过。谢谢。我要把你的标记为正确。但是为了完整起见,我建议您编辑您的答案,以包含user2357112提到的链接。除了给出答案外,还可以看到真实的事物。random。random本身并不实现\uuuuuuuuuu新的;它从\u random.random
继承了一个。请注意下划线random.random
实现了一个\uuuuu init\uuuu
方法,这使得使用它非常困难,因为您必须同时覆盖这两种方法,因为初始化顺序可能会变得非常奇怪。这是因为它是C中定义的一个类,还是仅仅是random的一个奇怪特性?@SeanMcSomething:random的一个奇怪的实现细节。random
@user2357112:不,大多数用C实现的类都是这样的。@Daniel:几乎没有类是这样的,无论是用C还是Python实现。像list
和dict
这样的类型只在\uuuu new\uuuuu
中设置一个空对象,并在\uuu init\uuuuu
中执行所有初始化,而像tuple
和int
这样的类型在\uuu new\uuuuu
中执行所有初始化,并且不实现它们自己的\uu init uuuuuu
。几乎没有类在\uuuuu init\uuuuu
和\uuuu new\uuuuu
中检查它们的参数。
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;
}