John Millikin เสนอวิธีแก้ปัญหาคล้ายกับ:
class A(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
return (isinstance(othr, type(self))
and (self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
def __hash__(self):
return hash((self._a, self._b, self._c))
hash(A(a, b, c)) == hash((a, b, c))
ปัญหาเกี่ยวกับการแก้ปัญหานี้ก็คือว่า กล่าวอีกนัยหนึ่งแฮชชนกับสิ่งอันดับของสมาชิกหลัก บางทีนี่อาจไม่สำคัญในทางปฏิบัติบ่อยนัก?
อัปเดต: ตอนนี้เอกสาร Python แนะนำให้ใช้สิ่งอันดับในตัวอย่างด้านบน โปรดทราบว่าเอกสารประกอบระบุ
คุณสมบัติที่จำเป็นเท่านั้นคือวัตถุที่เปรียบเทียบเท่ากับมีค่าแฮชเดียวกัน
โปรดทราบว่าสิ่งที่ตรงกันข้ามไม่เป็นความจริง วัตถุที่ไม่ได้เปรียบเทียบกันอาจมีค่าแฮชเหมือนกัน ดังกล่าวชนกัญชาจะไม่ได้เป็นสาเหตุหนึ่งวัตถุอื่นมาแทนเมื่อใช้เป็นคีย์ Dict หรือองค์ประกอบชุดตราบเท่าที่วัตถุที่ทำไม่ได้นอกจากนี้ยังเปรียบเทียบเท่ากับ
ทางออกที่ล้าสมัย / ไม่ดี
เอกสารหลามบน__hash__
แสดงให้เห็นในการรวมแฮชของส่วนประกอบย่อยใช้สิ่งที่ต้องการการ XORซึ่งจะช่วยให้เรานี้:
class B(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
def __eq__(self, othr):
if isinstance(othr, type(self)):
return ((self._a, self._b, self._c) ==
(othr._a, othr._b, othr._c))
return NotImplemented
def __hash__(self):
return (hash(self._a) ^ hash(self._b) ^ hash(self._c) ^
hash((self._a, self._b, self._c)))
อัปเดต: ตามที่ Blckknght ชี้ให้เห็นการเปลี่ยนลำดับของ a, b และ c อาจทำให้เกิดปัญหา ฉันเพิ่มส่วนเพิ่มเติม^ hash((self._a, self._b, self._c))
เพื่อจับลำดับของค่าที่ถูกแฮช ขั้นสุดท้ายนี้^ hash(...)
สามารถลบออกได้หากค่าที่รวมกันไม่สามารถจัดเรียงใหม่ได้ (ตัวอย่างเช่นหากมีประเภทที่แตกต่างกันดังนั้นค่าของ_a
จะไม่ถูกกำหนดให้กับ_b
หรือ_c
เป็นต้น)
__key
ฟังก์ชั่นออกมาสิ่งนี้จะเร็วพอ ๆ กับแฮชใด ๆ ก็ได้ แน่นอนว่าถ้าแอตทริบิวต์นั้นเป็นจำนวนเต็มและมีไม่มากเกินไปฉันคิดว่าคุณสามารถทำงานได้เร็วขึ้นเล็กน้อยด้วยแฮชที่ม้วนด้วยโฮม แต่อาจเป็นไปได้ว่าจะไม่กระจายไปhash((self.attr_a, self.attr_b, self.attr_c))
กำลังจะเกิดขึ้นอย่างรวดเร็วอย่างน่าประหลาดใจ (และถูกต้อง ) เนื่องจากการสร้างtuple
s ขนาดเล็กนั้นได้รับการปรับแต่งเป็นพิเศษและจะผลักดันการทำงานของการรวมและแฮชเข้ากับ C builtins ซึ่งโดยทั่วไปแล้วจะเร็วกว่ารหัสระดับ Python