2011-02-09 16 views
9

मैं एक ऑब्जेक्ट का उपयोग एक पायथन शब्दकोश में एक कुंजी के रूप में करने की कोशिश कर रहा हूं, लेकिन यह इस तरह से व्यवहार कर रहा है कि मैं काफी समझ नहीं पा रहा हूं।पाइथन शब्दकोशों में कुंजी के रूप में ऑब्जेक्ट्स

सबसे पहले मैं कुंजी के रूप में मेरी वस्तु के साथ एक शब्दकोश बनाने के लिए:

package_disseminators = { 
    ContentType("application", "zip", "http://other/property") : "one", 
    ContentType("application", "zip") : "two" 
} 

अब एक और उद्देश्य यह है कि एक चाबी है जो "एक ही" एक के रूप में है बनाएँ।

content_type = ContentType("application", "zip", "http://other/property") 

मैं कस्टम ContentType वस्तु __eq__ और कस्टम __str__ तरीकों, जैसे कि __eq__ विधि __str__ मूल्यों तुलना दे दिया है।

अब, कुछ इंटरैक्टिव अजगर:

>>> for key in package_disseminators: 
...  if key == content_type: 
...    print "match" 
...  else: 
...    print "no match" 
... 
no match 
match 

>>> content_type in package_disseminators.keys() 
True 

ठीक है, तो यह मेरी वस्तु की तरह दिखता है निश्चित रूप से एक कुंजी के रूप में ठीक तरह से पहचान की जा रही है, तो:

>>> package_disseminators[content_type] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
KeyError: (& (type="application/zip") (packaging="http://other/property")) 

एर ... ठीक है? तो content_type package_disseminators.keys() सूची में है, लेकिन एक कुंजी नहीं है?

>>> package_disseminators.has_key(content_type) 
False 

स्पष्ट रूप से नहीं।

मुझे लगता है कि समानता निर्धारित करने के लिए पाइथन का उपयोग एक सूची में सीधे "इन" कथन के बीच भिन्न होता है और वास्तव में एक निर्देश में एक कुंजी देखता है, लेकिन मुझे नहीं पता कि कैसे। कोई सुझाव या अंतर्दृष्टि?

उत्तर

17

अजगर प्रलेखन से:

एक शब्दकोश की कुंजियों लगभग मनमाना मूल्य हैं। वे मान जो हैंशबल नहीं हैं, यानी सूचियां, शब्दकोश या अन्य परिवर्तनीय प्रकार (जिनकी तुलना ऑब्जेक्ट पहचान के बजाए मूल्य द्वारा की जाती है) कुंजी के रूप में उपयोग नहीं की जा सकती है।

Hashable इस प्रकार परिभाषित किया गया है

एक वस्तु hashable है अगर यह एक हैश मूल्य है जो अपनी जीवनकाल के दौरान बदल जाता है कभी नहीं है (यह एक __hash__() विधि की जरूरत है), और अन्य की तुलना में किया जा सकता है ऑब्जेक्ट्स (इसे __eq__() या __cmp__() विधि की आवश्यकता है)। हैशबल ऑब्जेक्ट्स जो बराबर की तुलना में समान हैश मान होना चाहिए। क्योंकि इन डेटा संरचनाओं आंतरिक हैश मान का उपयोग

Hashability एक वस्तु एक शब्दकोश कुंजी और एक सेट सदस्य, के रूप में प्रयोग करने योग्य बनाता है।

तो अगर आप ऐसा करना चाहते हैं, तो आप अपने वस्तु पर डिफ़ॉल्ट __hash__() विधि (अधिक विवरण के लिए नीचे दिए गए स्टीवन Rumbalski से टिप्पणी देखें) ओवरराइड करने के लिए की जरूरत है।


>>> content_type in package_disseminators.keys() 
True 

मैं इस काम करता है क्योंकि dict.keys() एक सूची देता है, और __contains__ शायद समानता के लिए जाँच करता है, लेकिन एक ही हैश के लिए नहीं लगता है।

+6

कुछ और स्पष्टीकरण: आपके ऑब्जेक्ट में 'ऑब्जेक्ट 'से विरासत में मिली' __hash__' विधि है। लेकिन डिफ़ॉल्ट कार्यान्वयन प्रत्येक उदाहरण के लिए एक अद्वितीय मूल्य देता है, इसलिए दो बराबर उदाहरणों में अलग-अलग हैंश नहीं होंगे जबतक कि आप बेहतर कार्यान्वयन न करें। 'has_key' हैश मानों की तुलना करता है, 'समानता के लिए चेक' में, यही कारण है कि 'has_key' आपके उदाहरणों में सफल होने पर विफल रहता है। –

+0

हाय दोस्तों। बढ़िया, इसके लिए धन्यवाद, बहुत सराहना की! –

11

चूंकि हूड के नीचे हैश टेबल हैंश टेबल हैं, इसलिए आपको काम करने के लिए __eq__ और __hash__ दोनों को परिभाषित करने की आवश्यकता है।

अंगूठे का बुनियादी नियम है:

  • वस्तुओं के लिए कि __eq__ बराबर तुलना, __hash__ एक ही हैश वापस आना होगा।
अपने विवरण से

, जैसे

def __hash__(self): 
    return hash(str(self)) 

काम करना चाहिए कुछ।

+0

'__hash__' के कार्यान्वयन के लिए धन्यवाद! दुर्भाग्यवश मैं किसी प्रश्न के दो सही उत्तर आवंटित नहीं कर सकता, हालांकि आपके और दूसरे का संयोजन मुझे जो कुछ चाहिए, वह सब कुछ है। चीयर्स, आर। –

संबंधित मुद्दे