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;
}