शीर्षक जवाब देने के लिए: फिर भी, अगर हम सहयोगी 'tomorrow'
साथ bob
, हम अभी भी मूल्य bob
के साथ जुड़े लाने के लिए सक्षम हैं
__eq__
हैश का उपयोग कर बुलाया जाता है जब()?
कभी नहीं।
अन्य प्रश्न:
क्यों __eq__
जिम लेकिन बॉब पर नहीं पहुंचने से संबंधित बुलाया जाता है?
यह अधिक जटिल है। यह समझने के लिए कि आपको यह जानने की जरूरत है कि एक शब्दकोश कैसे कार्यान्वित किया जाता है। मान लिया जाये कि CPython यह एक hash
स्तंभ, एक key
स्तंभ और एक value
स्तंभ युक्त एक मेज हो जाएगा:
hash | key | value
-----------------------------------------
- | - | -
-----------------------------------------
- | - | -
यह एक निश्चित आकार होगा, लेकिन यह काफी बड़ा हर संभव hash
मान होना चाहिए नहीं होगा, तो यह hash
के आधार पर स्थिति की गणना करेगा। उदाहरण के लिए यदि आप bob
जोड़ सकते हैं तो यह हो सकता है (स्ट्रिंग हैश कुछ सीपीथॉन संस्करणों में यादृच्छिक हैं, इसलिए वास्तविक परिणाम अलग-अलग होंगे) hash
7475314405837642385
। शब्दकोश मान लिया जाये कि 2 का एक वास्तविक आकार की है (वास्तव में यह बड़ा हो जाएगा, लेकिन यह है कि अनावश्यक रूप से इस सवाल का जवाब में अंतरिक्ष बर्बाद होता है) यह सिर्फ सापेक्ष लेता है, तो यह 7475314405837642385 % 2 == 1
में रख देगा:
hash | key | value
-----------------------------------------
- | - | -
-----------------------------------------
747...385| bob | 'tomorrow'
जब आप एक महत्वपूर्ण यह
- हमेशा देखने
- तो यह स्थिति की गणना करेगा की
hash
गणना को देखने के लिए चाहते हैं।
- तो यह
hash
उस स्थिति
- में सहेजे गए देखने के
hash
तुलना अगर hash
तों बराबर तो यह देखने और PyObject_RichCompareBool
के साथ सहेजा key
तुलना करेंगे कर रहे हैं।यही कारण है कि इच्छा:
पहचान के लिए
- पहली जांच:
lookup is key
- कि अगर
False
है यह lookup == key
की जाँच करेगा तो मामले में आप देखने bob
:
- हैश:
7475314405837642385
- po sition:
7475314405837642385 % 2
->1
- एक प्रवेश पाया, तो तुलना
hash
तों: 7475314405837642385 == 7475314405837642385
- कि बराबर तो पहचान के लिए जाँच था:
bob is bob
->True
तो यह 'tomorrow'
रिटर्न एक समानता की जांच के बिना। दूसरे मामले में यह jim
लिए जाँच करता है:
- हैश:
7475314405837642385
- स्थिति:
7475314405837642385 % 2
->1
- एक प्रवेश मिल गया है, तो
hash
तों तुलना: 7475314405837642385 == 7475314405837642385
- कि बराबर तो के लिए जाँच था पहचान:
jim is bob
->False
- समानता के लिए चेक
jim == bob
->True
तो यह 'tomorrow'
देता है।
यह वास्तविक कार्यान्वयन का अनुमान है (इसमें कुछ विवरण गुम हैं)। hash
ई बराबर या lookup is not key and lookup != key
के बराबर नहीं हैं, लेकिन यह आपके द्वारा पूछे जाने वाले व्यवहार को समझने के लिए वास्तव में महत्वपूर्ण नहीं है, यह अधिक जटिल हो जाता है।
हालांकि, मुझे वास्तव में यह कहना है: आप जो कर रहे हैं वह वास्तव में खतरनाक है क्योंकि आपकी कक्षा अपरिवर्तनीय नहीं है। आप गलती से बचाया शब्दकोश प्रविष्टि आपके लिए अनुपलब्ध बना सकता है:
dmv_appointments = {bob: 1}
bob.ssn = '1' # changing ssn changes the hash!
dmv_appointments[bob]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-35-3920ada7bab1> in <module>()
15 dmv_appointments = {bob: 1}
16 bob.ssn = '1'
---> 17 dmv_appointments[bob]
KeyError: <__main__.Person object at 0x000001BD5DDCC470>
(यह अभी भी मामले में काम कर सकता था नई hash
"पुराने" हैश के बराबर है, लेकिन वह नहीं बल्कि आकस्मिक होगा)।
क्योंकि जब आप अपने उदाहरण के hash
बदल है कि - क्योंकि यह मान लिया गया है शब्दकोश बचाया hash
अपडेट नहीं करेंगे सभी कुंजियों अपरिवर्तनीय कर रहे हैं! तो शब्दकोश या तो यह मान लेगा कि यह किसी अन्य स्थिति में सहेजा जाएगा या यदि स्थिति (चमत्कारी रूप से) समान होगी तो यह उस चरण में विफल हो जाएगी जहां इसमें वास्तविक हैंश शामिल हैं।
मेरा अनुमान है कि यह पहले हैश की जांच कर रहा है, फिर _identity_ (तेज़ होने), और केवल _then_ समानता। इस प्रकार, जब आप 'बॉब' देखते हैं तो यह देखने के लिए '__eq__'' की जांच नहीं करनी है कि यह सही प्रविष्टि है, लेकिन 'jim' के लिए यह करता है। –
संबंधित प्रश्न: https: // stackoverflow।कॉम/क्यू/40 9 77986/1639625 एक टिप्पणी सी कार्यान्वयन में यह कैसे किया जाता है इसके बारे में कुछ कहता है। –
@tobias_k: हाँ, यह एक सीपीथन (पायथन संदर्भ दुभाषिया) कार्यान्वयन विस्तार है [सीओ परत पर वस्तुओं की तुलना करने के लिए मानक विधि के रूप में 'PyObject_RichCompareBool' का उपयोग करके] (https://docs.python.org/3/c -api/object.html # c.PyObject_RichCompareBool)। समानता जांच के लिए उस फ़ंक्शन का उपयोग करना पाइथन स्तर पर 'वापसी x है y या x == y' के बराबर प्रभावी है। – ShadowRanger