开发者

Problem subclassing random.Random (python /CPython 2.6)

开发者 https://www.devze.com 2023-02-13 19:49 出处:网络
I have tried this code snippet in CPython 2.6 (original python implementation): from random import Random, random

I have tried this code snippet in CPython 2.6 (original python implementation):

from random import Random, random

class Uniform(Random, object):
    def __init__(self,  min,  max):
        self._min =min
        se开发者_开发知识库lf._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()

Although it seems to be CORRECT pythonic inheritance, it throws this error:

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

But if you define

def __init__(self,  min,  max):

as

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

things will miraculously go on "correctly".. but the first generated random numbers will be always the same for all instances of Uniform (because of the same initial seed!).

PROBLEM SOURCE

The random.Random class IS new-style class and definitely it is NOT basic class (see /usr/lib/python2.6/random.py on Unix and its equivalent on Win). So hacks about subclassing of built-in classes -- will be in our course. The random.Random class -- despite of its new-style nature subclasses at first class written in C (in /usr/lib/python2.6/random.py see import _random -and it is built-in class!).

What does it mean? We need to override __new__ method as if it was builtin class itself (more here: problem subclassing builtin type).

FINAL WORKAROUND IN SHORT

Just add overriding of __new__ method (that random() was imported in the 2nd line of this "question" and is just object passed behind the scene to random.Random.seed(x) to initialize the object seed (in source of /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

Enjoy the built-in Mersenne Twister random number generator in Python ;-) Good LUCK!


You need to call Random.__init__(self, seed) at the beginning of your constructor (the seed argument is optional):

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

Also, I don't quite understand why you are explicitly extending object as well; extending Random should suffice.

0

精彩评论

暂无评论...
验证码 换一张
取 消