为什么我不能分配`cls.__hash__ = id`?

Ban*_*ach 7 python attributes class

我希望这有效(在 Python 3.6 中),

class A:
    __hash__ = id
A().__hash__()
Run Code Online (Sandbox Code Playgroud)

但我明白了

TypeError: id() takes exactly one argument (0 given)
Run Code Online (Sandbox Code Playgroud)

出奇,

def my_id(self):
    return id(self)
class A:
    __hash__ = my_id
A().__hash__()
Run Code Online (Sandbox Code Playgroud)

按预期工作。

bru*_*ers 8

id是类型builtin_function_or_method(它是一个内置在运行时中的函数 - ),出于实际原因(主要是优化),它没有descriptor像 python 函数那样实现协议,因此A().__hash__解析为id函数本身,而不是method封装函数的对象。

您将观察到大多数内置函数 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__'
Run Code Online (Sandbox Code Playgroud)

等等...