Why can I not assign `cls.__hash__ = id`?

Viewed 119

I would have hoped this works (in Python 3.6),

class A:
    __hash__ = id
A().__hash__()

but I get

TypeError: id() takes exactly one argument (0 given)

Surprisingly,

def my_id(self):
    return id(self)
class A:
    __hash__ = my_id
A().__hash__()

works as hoped.

1 Answers

id is of type builtin_function_or_method (it's a function that's built into the runtime - ), which for practical reasons (optimisation mainly) doesn't implement the descriptor protocol as a python function would, so A().__hash__ resolves to the id function itself, not to a method object wrapping the function.

You'll observe the same behaviour with most builtin functions FWIW:

>>> type(len)
<class 'builtin_function_or_method'>
>>> len.__get__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'
>>> 
>>> type(all)
<class 'builtin_function_or_method'>
>>> all.__get__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'
>>> type(abs)
<class 'builtin_function_or_method'>
>>> abs.__get__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'
>>> type(isinstance)
<class 'builtin_function_or_method'>
>>> isinstance.__get__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'

etc...

Related