ngắn câu trả lời: một tra cứu từ điển đầu tiên thực hiện một (rẻ) tham khảo kiểm tra bình đẳng (x is y
) khi tìm kiếm một cái xô, và chỉ khi thất bại, một tấm séc (đắt hơn) bình đẳng (x == y
) được thực hiện.
Kịch bản
Chức năng __hash__
không không gọi__eq__
nội bộ. Do bạn xây dựng bob
và jim
, không có phương pháp nào được gọi.
Tiếp theo, bạn liên kết bob
với 'tomorrow'
. Để biết trong đó có từ điển của từ điển, bạn phải lưu trữ bob
, bạn tính giá trị băm. Bây giờ, khi bạn đã thực hiện xong, chúng tôi lưu trữ bob
(và giá trị trong nhóm chính xác).
Tiếp theo, chúng tôi muốn lấy jim
. Để biết được số thùng nào jim
, chúng tôi tính giá trị băm. Tiếp theo, chúng tôi bắt đầu tìm kiếm trong nhóm. Thùng chứa sẽ chứa bob
. Trước tiên, chúng tôi thực hiện kiểm tra tham chiếu (jim is bob
) nhưng không thành công, vì vậy, chúng tôi dự phòng số séc bình đẳng. Việc kiểm tra đó thành công, vì vậy chúng tôi trả lại giá trị tương ứng với bob
: 'tomorrow'
.
Kịch bản tương tự cũng xảy ra khi chúng tôi muốn tìm kiếm bob
: chúng tôi tính giá trị băm, tìm nạp nhóm. Thực hiện kiểm tra tham chiếu trên bob is bob
và điều đó thành công. Vì vậy, chúng tôi không cần một (có thể kiểm tra bình đẳng đắt tiền hơn). Chúng tôi chỉ trả lại giá trị 'tomorrow'
.
kiểm tra tham khảo
Thực tế là một tấm séc tài liệu tham khảo được thực hiện đầu tiên có thể được chứng minh như sau (không lành mạnh) mã:
class Person(object):
def __init__(self, name, ssn, address):
self.name = name
self.ssn = ssn
self.address = address
def __hash__(self):
print('in hash')
return hash(self.ssn)
def __eq__(self, other): print('in eq') return False
Ở đây chúng ta quay trở lại luôn False
cho sự bình đẳng.Vì vậy, mặc:
>>> bob == bob
in eq
False
>>> bob is bob
True
bob
không bằng bản thân (điều này thực sự là thiết kế không tốt, vì đối với một cuốn từ điển, nó là một hợp đồng mà một đối tượng là tương đương với bản thân: a tốt bình đẳng liên quan là phản, đối xứng và transitive). Tuy nhiên, nếu chúng ta kết hợp với bob
'tomorrow'
, chúng ta vẫn có thể lấy giá trị gắn liền với bob
:
>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'
in hash
>>> dmv_appointments[bob]
in hash
'tomorrow'
Đoán của tôi là lần đầu tiên kiểm tra hàm băm, sau đó _identity_ (nhanh hơn) và chỉ _then_ bình đẳng. Vì vậy, khi bạn tra cứu 'bob', nó không phải kiểm tra' __eq__' để xem nó có phải là mục nhập đúng hay không, nhưng đối với 'j'' thì nó sẽ làm. –
Câu hỏi liên quan: https: // stackoverflow.com/q/40917986/1639625 Một bình luận nói điều gì đó về cách nó được thực hiện trong việc thực hiện C. –
@tobias_k: Vâng, đó là một chi tiết thực hiện CPython (thông dịch tham khảo Python) do [sử dụng 'PyObject_RichCompareBool' làm phương thức chuẩn để so sánh các đối tượng ở lớp C] (https://docs.python.org/3/c -api/object.html # c.PyObject_RichCompareBool). Sử dụng hàm đó để kiểm tra bình đẳng có hiệu quả tương đương với 'return x là y hoặc x == y' ở mức Python. – ShadowRanger