Python重写__init__

2024-09-27 07:20:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道很多人都会问这个问题,但我还没有看到我具体的问题。子类化时,您可以重写__init__(),方法与重写任何其他方法的方式相同。下面的问题是为什么我的例子不正确:

import random
class MyRand(random.Random):
    def __init__(self, myvar1, myvar2, x=None):
        # ( ... my code ...)
        super(MyRand, self).__init__(x)

请记住,Random的构造函数具有以下签名:__init__(self, x=None),其中x是可选种子。我想在我的子类中保留这个特性,但也需要两个强制变量,myvar1和{}。在

但是,当您尝试实例化(没有种子)时,会出现错误:

^{pr2}$

这是因为python认为您需要Random的构造函数,并将两个参数“var1”和“var2”作为种子传递。seed(从Random的构造函数内部调用)只需要1个参数,因此会得到一个错误。在

但是,如果你这么做

MyRand(myvar1='var1', myvar2='var2')

这是可行的,在这里python理解为传递两个强制变量而不是传递可选种子。在

但我认为第一个案子也应该行得通。发生什么事?在


Tags: 方法selfnone参数init错误方式random
2条回答

你把问题诊断错了一点。问题是random.Random的初始化并没有完全包含在random.Random.__init__中。它还继承了^{}

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

您也将不得不重写__new__,并且只传递它期望的seed参数,位置上(因为它不将其理解为关键字参数)。在

它们真的不应该像这样混合__init__和{}。当你这样做的时候,初始化顺序会变得很奇怪。在

在Python中,创建对象时调用两个方法。__new____init__。与许多用C实现的类一样,random.Random使用__new__来初始化自身(参见random_new)。您必须覆盖它并使用适当的参数调用它:

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 ...)

相关问题 更多 >

    热门问题