أنواع تحديد `__eq__` هي unhashable?
-
05-07-2019 - |
سؤال
كان غريب الخلل عند ترقية ميزة الثعبان 3.1 شوكة من البرنامج.لقد ضيقت على الفرضية التالية:
وعلى النقيض من بيثون 2.x في بيثون 3.× إذا كان كائن يحتوي على __eq__
الأسلوب هو تلقائيا unhashable.
هل هذا صحيح ؟
هنا ما يحدث في بيثون 3.1:
>>> class O(object):
... def __eq__(self, other):
... return 'whatever'
...
>>> o = O()
>>> d = {o: 0}
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
d = {o: 0}
TypeError: unhashable type: 'O'
متابعة السؤال هو كيف يمكنني حل رأيي الشخصي المشكلة ؟ أنا كائن ChangeTracker
الذي يخزن WeakKeyDictionary
الذي يشير إلى عدة كائنات ، مما يتيح لكل قيمة المخلل تفريغ عند نقطة زمنية معينة في الماضي.كلما كائن موجود هو مؤكد في التغيير تعقب يقول إذا الجديدة المخلل هو نفس القديم, ولذلك أقول ما إذا كان الكائن قد تغير في الوقت الحالي.المشكلة الآن لا أستطيع حتى تحقق ما إذا كان كائن معين في المكتبة ، لأنه يجعل من رفع استثناء عن الكائن الذي unhashable.(لأنه لديه __eq__
الأسلوب.) كيف يمكن التغلب على هذه المشكلة ؟
المحلول
نعم، إذا قمت بتعريف __eq__
، و__hash__
الافتراضي (أي تجزئة عنوان الكائن في الذاكرة) يذهب بعيدا. هذا أمر مهم لأن التجزئة تحتاج إلى أن تكون متسقة مع المساواة: المساواة في الأشياء تحتاج إلى تجزئة نفسه
والحل بسيط: فقط تحديد __hash__
جنبا إلى جنب مع تحديد __eq__
نصائح أخرى
هذه الفقرة من http://docs.python.org/3.1/reference/datamodel.html#object.تجزئة
إذا كانت الفئة التي يتجاوز
__eq__()
تحتاج إلى الاحتفاظ تنفيذ__hash__()
من فئة الأم, يجب أن يكون المترجم قال هذا صراحة من خلال وضع__hash__ = <ParentClass>.__hash__
.وإلا الميراث__hash__()
سوف يكون منعت ،__hash__
كان صراحة لا شيء.
التحقق من بيثون 3 دليل object.__hash__
:
إذا فئة لا تعريف
__eq__()
الأسلوب يجب أن لا تحدد__hash__()
العملية سواء ؛ إذا كان يعرف__eq__()
ولكن ليس__hash__()
, ، في الحالات التي لا يمكن استخدامها كعناصر في hashable مجموعات.
التركيز هو الألغام.
إذا كنت تريد أن تكون كسول ، يبدو مثل يمكنك فقط تحديد __hash__(self)
العودة id(self)
:
المعرفة من قبل المستخدم الطبقات
__eq__()
و__hash__()
أساليب افتراضيا ؛ مع كل الكائنات مقارنة غير متكافئة (إلا أنفسهم) ،x.__hash__()
يعودid(x)
.
وأنا لست خبيرا الثعبان، ولكن لن يكون من المنطقي أنه عند تحديد مكافئ، طريقة، لديك أيضا لتحديد تجزئة-طريقة وكذلك (الذي يحسب قيمة التجزئة لكائن) وإلا، ان آلية التجزئة لا نعرف ما اذا كان ضرب نفس الكائن، أو كائن آخر فقط مع نفس القيمة التجزئة. في الواقع، انها على العكس من ذلك، فإنه على الأرجح في نهاية المطاف الحوسبة قيم التجزئة المختلفة للكائنات تعتبر متساوية بطريقة __eq__
الخاص بك.
وليس لدي أي فكرة عما يسمى ذلك ظيفة تجزئة على الرغم من __hash__
ربما؟ :)