我知道有很多人就这个问题提出问题,但我没有看到我的具体问题.子类化时,您可以覆盖__init__()与覆盖任何其他方法相同的方式.我的问题是为什么在下面的例子中这似乎没有正常工作:
import random
class MyRand(random.Random):
def __init__(self, myvar1, myvar2, x=None):
# ( ... my code ...)
super(MyRand, self).__init__(x)
Run Code Online (Sandbox Code Playgroud)
请记住,Random构造函数具有以下签名:__init__(self, x=None)where x是可选种子.我想在我的子类中保留该功能,但我也想要两个必需的变量,myvar1和myvar2.
但是,当您尝试实例化(没有种子)时会出现错误:
MyRand('var1', 'var2')
TypeError: seed expected at most 1 arguments, got 2
Run Code Online (Sandbox Code Playgroud)
这是因为python认为你想要Random的构造函数并传递你的两个参数'var1'和'var2'作为种子.种子(从内部Random的构造函数调用)只需要1个参数,因此您会收到错误.
但是,如果你这样做
MyRand(myvar1='var1', myvar2='var2')
Run Code Online (Sandbox Code Playgroud)
这是有效的,这里python知道你传递它的两个必需变量而不传递可选种子.
但我认为第一种情况也应该奏效.这是怎么回事?
Dan*_*iel 11
在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 ...)
Run Code Online (Sandbox Code Playgroud)
你错误地诊断了这个问题.问题是random.Random初始化并不完全包含在内random.Random.__init__.它还继承了_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;
}
Run Code Online (Sandbox Code Playgroud)
你也必须重写__new__,并且只能按seed位置传递它所期望的参数(因为它不能将它理解为关键字参数).
他们真的不应该混合__init__和__new__这样.当你这样做时,初始化顺序变得非常奇怪.
| 归档时间: |
|
| 查看次数: |
2569 次 |
| 最近记录: |