问题继承random.Random(python / CPython 2.6)

时间:2011-02-28 22:12:04

标签: python random subclass built-in

我在CPython 2.6(原始python实现)中尝试过这段代码:

from random import Random, random

class Uniform(Random, object):
    def __init__(self,  min,  max):
        self._min =min
        self._max =max
    def randint(self):
        return super(Uniform, self).randint (self._min,  self._max)
    def uniform(self):
        return super(Uniform, self).uniform(self._min,  self._max)

if __name__ == '__main__':
    a=Uniform(0.,  1.2)
    print a.uniform()
    print a.randint()

虽然它似乎是 CORRECT pythonic继承,但它会抛出此错误:

/tmp/source.py in <module>()
     11 
     12 if __name__ == '__main__':
---> 13   a=Uniform(0.,  1.2)
     14   print a.uniform()
     15   print a.randint()

TypeError: seed expected at most 1 arguments, got 2
WARNING: Failure executing file: </tmp/source.py>

但是如果你定义

def __init__(self,  min,  max):

作为

def __init__(self,  (min,  max)):

事情会奇迹般地“正确地”继续......但是所有Uniform实例的第一个生成的随机数总是相同的(因为相同的初始种子!)。

问题来源

random.Random类是新式类,绝对不是基本类(请参阅Unix上的/usr/lib/python2.6/random.py及其在Win上的等效类)。关于内置类的子类化的黑客攻击 - 将在我们的课程中。 random.Random类 - 尽管它的新风格自然子类在第一类用C 编写(在/usr/lib/python2.6/random.py中见import _random - 它是内置类!)。

这是什么意思?我们需要覆盖__new__方法,就好像它是在类内部构建的一样(更多信息:problem subclassing builtin type)。

简短的最终解决方法

只需添加覆盖__new__方法(在此“问题”的第二行导入random(),并且只是将对象传递到场景后面random.Random.seed(x)以初始化对象种子(在/usr/lib/python2.6/random.py的源代码中)。

class Uniform(Random, object):
    def __new__(cls, *args, **kwargs):
        return super (Uniform, cls).__new__ (cls, random() )
    def __init__(self,  min,  max):
        self._min =min
        self._max =max

享受Python内置的Mersenne Twister随机数生成器;-)祝你好运!

1 个答案:

答案 0 :(得分:0)

您需要在构造函数的开头调用Random.__init__(self, seed)seed参数是可选的):

def __init__(self,  min,  max):
    Random.__init__(self)  # Use the default seed.
    self._min =min
    self._max =max

另外,我不太清楚为什么你明确地扩展object;延长Random就足够了。