子类化random.Random存在的问题(Python/CPython 2.6)

4

我已经在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()

虽然看起来是正确的Python继承,但会抛出此错误:

/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):

as

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

事情会神奇地“正确”进行,但是Uniform的所有实例的第一个生成的随机数将始终相同(因为初始种子相同!)。

问题来源

random.Random类是新式类,绝对不是基本类(在Unix上请参见/usr/lib/python2.6/random.py及其Windows等效项)。因此,关于内置类的子类化的黑客将出现在我们的课程中。尽管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中,您可以使用内置的梅森旋转器随机数生成器。祝你好运!
1个回答

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应该就足够了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接