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?
This error occurs when trying to hash a list, which is an unhashable object. For example, using a list as a key in a Python dictionary will cause this error since dictionaries only accept hashable data types as a key. The standard way to solve this issue is to cast a list to a tuple, which is a hashable data type.
TypeError: unhashable type: 'list' usually means that you are trying to use a list as an hash argument. This means that when you try to hash an unhashable object it will result an error. For ex. when you use a list as a key in the dictionary , this cannot be done because lists can't be hashed.
We can solve this by adding each array element instead of the array object into the set. This should add all the elements of the array to the set.
The “TypeError: unhashable type: 'list'” error is raised when you try to assign a list as a key in a dictionary. To solve this error, ensure you only assign a hashable object, such as a string or a tuple, as a key for a dictionary.
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With