2011-06-10 23 views
44

मैंने एक ब्लॉग पोस्ट में ठोकर खाई कि पाइथन में एक पावरसेट फ़ंक्शन को कैसे कार्यान्वित किया जाए। तो मैं इसे करने का अपना रास्ता तय करने के बारे में गया, और पाया कि पायथन स्पष्ट रूप से सेट का सेट नहीं रख सकता है, क्योंकि सेट हैशबल नहीं है। यह अजीब है, क्योंकि एक पावरसेट की परिभाषा यह है कि यह सेट का एक सेट है, और मैं इसे वास्तविक सेट ऑपरेशंस का उपयोग करके कार्यान्वित करना चाहता था।पायथन सेट क्यों नहीं है?

>>> set([ set() ]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'set' 

क्या कोई अच्छा कारण है कि पाइथन सेट हैंशबल नहीं हैं?

+3

कुछ भी जो अपरिवर्तनीय नहीं है आम तौर पर खराब कुंजी बनाता है। यदि आपको करना है तो आप टुपल्स का उपयोग कर सकते हैं। –

उत्तर

81

आम तौर पर, पाइथन में केवल अपरिवर्तनीय वस्तुएं हैंशबल होती हैं। set() - frozenset() का अपरिवर्तनीय संस्करण - हैशबल है।

+5

और पाइथन FAQ प्रविष्टि देखें [शब्दकोश कुंजी को अपरिवर्तनीय क्यों होना चाहिए?] (Http://docs.python.org/3.3/faq/design।एचटीएमएल # why-चाहिए-शब्दकोश कुंजी-हो-अपरिवर्तनीय)। – abarnert

22

क्योंकि वे उत्परिवर्तनीय हैं।

यदि वे हैंशबल थे, तो हैश चुपचाप "अमान्य" हो सकता है, और इससे काफी हद तक परेशानी होगी।

15
अजगर डॉक्स से

:

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

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

निर्मित वस्तुओं पायथन के अपरिवर्तनीय सब के सब, hashable हैं। ऑब्जेक्ट्स जो उपयोगकर्ता परिभाषित कक्षाओं के उदाहरण डिफ़ॉल्ट रूप से हैशबल हैं; वे सभी असमान की तुलना करते हैं, और उनके हैश मान उनके आईडी() हैं।

4

मामले में इस में मदद करता है ... यदि आप वाकई hashable समकक्ष में किसी कारण आप कुछ इस तरह कर सकते हैं के लिए unhashable चीजें बदलने की आवश्यकता:

from collections import Hashable, MutableSet, MutableSequence, MutableMapping 

def make_hashdict(value): 
    """ 
    Inspired by https://stackoverflow.com/questions/1151658/python-hashable-dicts 
    - with the added bonus that it inherits from the dict type of value 
     so OrderedDict's maintain their order and other subclasses of dict() maintain their attributes 
    """ 
    map_type = type(value) 

    class HashableDict(map_type): 
     def __init__(self, *args, **kwargs): 
      super(HashableDict, self).__init__(*args, **kwargs) 
     def __hash__(self): 
      return hash(tuple(sorted(self.items()))) 

    hashDict = HashableDict(value) 

    return hashDict 


def make_hashable(value): 
    if not isinstance(value, Hashable): 
     if isinstance(value, MutableSet): 
      value = frozenset(value) 
     elif isinstance(value, MutableSequence): 
      value = tuple(value) 
     elif isinstance(value, MutableMapping): 
      value = make_hashdict(value) 

     return value 

my_set = set() 
my_set.add(make_hashable(['a', 'list'])) 
my_set.add(make_hashable({'a': 1, 'dict': 2})) 
my_set.add(make_hashable({'a', 'new', 'set'})) 

print my_set 

मेरे HashableDict कार्यान्वयन सरल और कम से कम कठोर है उदाहरण here से। यदि आपको अधिक उन्नत हैशबल डिक्ट की आवश्यकता है जो पिकलिंग और अन्य चीजों का समर्थन करता है, तो कई अन्य कार्यान्वयन की जांच करें। उपरोक्त मेरे संस्करण में मैं मूल डॉट क्लास को संरक्षित करना चाहता था, इस प्रकार ऑर्डर्डडिक्ट के आदेश को संरक्षित करता था। मैं विशेषता-जैसी पहुंच के लिए here से AttrDict का भी उपयोग करता हूं।

ऊपर मेरा उदाहरण किसी भी तरह से आधिकारिक नहीं है, केवल एक ही समस्या के लिए मेरा समाधान जहां मुझे कुछ चीजों को एक सेट में स्टोर करने की आवश्यकता थी और उन्हें पहले "हैशिफी" करने की आवश्यकता थी।

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