Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python random.Random(bytearray) TypeError: unhashable type

Tags:

python

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?

like image 776
JHSN Avatar asked Dec 11 '18 17:12

JHSN


People also ask

How do I fix Unhashable type list?

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.

What does Unhashable type mean Python?

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.

How do I fix Unhashable type NumPy Ndarray?

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.

Why are lists Unhashable?

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.


2 Answers

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>
like image 91
BlackJack Avatar answered Oct 30 '22 07:10

BlackJack


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.

like image 30
JHSN Avatar answered Oct 30 '22 06:10

JHSN