Nó rất dễ dàng để thấy rằng tùy chọn # 3 giữ cho người dùng định nghĩa các đối tượng. Điều này cho phép băm thay đổi nếu bạn thay đổi đối tượng, nhưng nếu bạn sử dụng đối tượng làm khóa từ điển, bạn phải chắc chắn ngăn chặn băm thay đổi.
>>> class C:
def __hash__(self):
print("__hash__ called")
return id(self)
>>> inst = C()
>>> hash(inst)
__hash__ called
43795408
>>> hash(inst)
__hash__ called
43795408
>>> d = { inst: 42 }
__hash__ called
>>> d[inst]
__hash__ called
Tùy chọn sử dụng chuỗi # 2: họ tính giá trị băm một lần và lưu vào bộ nhớ cache kết quả. Điều này là an toàn vì các chuỗi không thay đổi được nên băm không bao giờ có thể thay đổi, nhưng nếu bạn phân lớp str
kết quả có thể không thay đổi, do đó phương pháp __hash__
sẽ được gọi lại mỗi lần nữa. Tuple thường được coi là không thay đổi, do đó bạn có thể nghĩ rằng băm có thể được lưu trữ, nhưng trên thực tế, băm của tuple phụ thuộc vào hàm băm của nội dung và có thể bao gồm các giá trị có thể thay đổi.
Đối @max người không tin rằng lớp con của str
có thể sửa đổi các hash:
>>> class C(str):
def __init__(self, s):
self._n = 1
def __hash__(self):
return str.__hash__(self) + self._n
>>> x = C('hello')
>>> hash(x)
-717693723
>>> x._n = 2
>>> hash(x)
-717693722
3 là ra như tôi đã [đọc] (http://www.laurentluce.com/posts/ python-dictionary-implementation /) nó được lưu trữ trong lần đầu tiên nó được gọi.Tôi sẽ giả sử tùy chọn thứ 2 là đúng nhưng tôi không chắc chắn tôi sẽ không đăng nó như là một câu trả lời :) – rplnt
@ rplnt: sai; đó chỉ đơn thuần là khi nói về một cuốn từ điển. Băm của nó sẽ được lưu trữ trong từ điển, nhưng điều đó không đúng với băm chung. –
@ChrisMorgan Thực ra tôi không nghĩ rằng giá trị băm python 'dict' lưu trữ các giá trị băm của nó. Tất nhiên, các lớp riêng lẻ có thể làm bất cứ điều gì họ thích trong hàm '__hash__' của họ, vì vậy bài báo được đề cập ở trên nói rằng' str' lưu trữ giá trị băm của nó. – max