Проблема подклассов случайных. Случайно (python / CPython 2.6) - PullRequest
4 голосов
/ 01 марта 2011

Я попробовал этот фрагмент кода в 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()

Хотя кажется, что ПРАВИЛЬНО Питоническое наследование, он выдает эту ошибку:

/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 является классом нового стиля и определенно НЕбазовый класс (см. /usr/lib/python2.6/random.py для Unix и его эквивалент для Win).Так что взломать насчет подклассов встроенных классов - будет в нашем курсе.Класс random.Random - несмотря на его подклассы природы нового стиля в первом классе, написанном на C (в /usr/lib/python2.6/random.py см. import _random - и это встроенный класс !).

Что это значит?Нам нужно переопределить метод __new__ так, как если бы он был встроен в сам класс (подробнее здесь: проблема создания подкласса встроенного типа ).

ЗАКЛЮЧИТЕЛЬНЫЙ РАБОТЫ ЗА КОРОТКОЕ

Просто добавьте переопределение метода __new__ (чтобы random() было импортировано во 2-й строке этого «вопроса» и было просто объектом, переданным за сценой в 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

Наслаждайтесь встроенным генератором случайных чисел Mersenne Twister в Python ;-) Удачи!

1 Ответ

0 голосов
/ 01 марта 2011

Вам нужно вызвать 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 должно быть достаточным.

...