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()
正しい 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__
(詳細はこちら:組み込み型のサブクラス化の問題)。
要するに最終的な回避策
__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
Python に組み込まれている Mersenne Twister 乱数ジェネレーターをお楽しみください ;-) がんばってください!