Python random.Random(bytearray)TypeError:无法散列的类型

时间:2018-12-11 17:24:57

标签: python

在Python3中,random.Random(seed)允许使用字节数组进行播种。

class Random(_random.Random):
    ...
    def __init__(self, x=None):
        self.seed(x)
        ...

    def seed(self, a=None, version=2):
        ...
        if version == 2 and isinstance(a, (str, bytes, bytearray)):
            if isinstance(a, str):
                a = a.encode()
            a += _sha512(a).digest()
            a = int.from_bytes(a, 'big')
        ...

尝试时

>>> random.Random().__init__(bytearray([1, 2, 3]))

>>> r = random.Random()
>>> r.seed(bytearray([1, 2, 3]))

它将正常工作。

但是当您尝试这样做时,结果不一致。

>>> random.Random(bytearray([1, 2, 3]))
TypeError: unhashable type: 'bytearray'

我编译并调试了python 3.7.0二进制文件,当尝试使用字节数组初始化PRNG时,它将调用Modules / _randommodule.c中的random_seed方法,并在此处直接引发typeerror。为什么?

2 个答案:

答案 0 :(得分:2)

该异常不是来自Random.__init__()方法,而是来自__new__()方法,该方法在__init__()之前被调用:

>>> random.Random.__new__(random.Random, bytearray([1,2,3]))
TypeError: unhashable type: 'bytearray'
>>> random.Random.__new__(random.Random, bytes([1,2,3]))
<random.Random at 0x1b0cd78>

答案 1 :(得分:1)

BlackJack's answer启发了我。我仔细阅读了_random.Random.__new__方法的C source code

_random.Random.__new__方法(在C中为random_new)使用相同的参数调用_random.Random.seed方法(在C中为random_seed)。如果args函数中的random_seed包含一个非整数对象作为种子,它将尝试get the hash value该对象。因此,当对象是字节数组时,它将引发类型错误。

因此,_random.Random并没有专门处理字节数组的种子处理,但是其子类random.Random可以处理,这似乎是不兼容的python错误。