Reputation: 91
In Python3, random.Random(seed) allows to seed using a bytearray.
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')
...
When you try
>>> random.Random().__init__(bytearray([1, 2, 3]))
or
>>> r = random.Random()
>>> r.seed(bytearray([1, 2, 3]))
it will work without exception.
But when you try this, the result is inconsistent.
>>> random.Random(bytearray([1, 2, 3]))
TypeError: unhashable type: 'bytearray'
I compiled and debuged python 3.7.0 binary, when tried to init a PRNG with a bytearray, it will invoke random_seed
method in Modules/_randommodule.c and directly raise a typeerror here. Why?
Upvotes: 8
Views: 875
Reputation: 91
BlackJack's answer enlightened me. I read the C source code of the _random.Random.__new__
method carefully.
The _random.Random.__new__
method (random_new
in C) invokes _random.Random.seed
method (random_seed
in C) with the same arguments. If the args
in the random_seed
function contains a non-int object as a seed, it will try to get the hash value of the object. So it will raise a type error when the object is a bytearray.
Thus, _random.Random
doesn't specially handle seeding with a bytearray but its subclass random.Random
did, which seems like an incompatible python bug.
Upvotes: 1
Reputation: 4689
The exception doesn't come from the Random.__init__()
method but from the __new__()
method, which is called before __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>
Upvotes: 2