दो वस्तुओं के बराबर होने पर एक पायथन सेट ([]) कैसे जांचता है? इसे अनुकूलित करने के लिए किसी वस्तु को परिभाषित करने के लिए किन तरीकों की आवश्यकता होती है?


85

मुझे पायथन में एक 'कंटेनर' ऑब्जेक्ट या क्लास बनाने की ज़रूरत है, जो अन्य वस्तुओं का रिकॉर्ड रखता है जिसे मैं भी परिभाषित करता हूं। इस कंटेनर की एक आवश्यकता यह है कि यदि दो वस्तुओं को एक समान माना जाता है, तो एक (या तो) को हटा दिया जाता है। मेरा पहला विचार set([])इस आवश्यकता को पूरा करने के लिए युक्त वस्तु के रूप में उपयोग करना था ।

हालाँकि, सेट दो समान ऑब्जेक्ट इंस्टेंस में से एक को नहीं निकालता है। मुझे एक बनाने के लिए क्या परिभाषित करना चाहिए?

यहाँ पायथन कोड है।

class Item(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __repr__(self):
    return "Item(%s, %s)" % (self.foo, self.bar)
  def __eq__(self, other):
    if isinstance(other, Item):
      return ((self.foo == other.foo) and (self.bar == other.bar))
    else:
      return False
  def __ne__(self, other):
    return (not self.__eq__(other))

दुभाषिया

>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])

यह स्पष्ट है कि __eq__(), जिसे कहा जाता है x == y, वह सेट द्वारा कहा जाने वाला तरीका नहीं है। क्या कहते हैं? मुझे किस अन्य विधि को परिभाषित करना चाहिए?

ध्यान दें: Items को परिवर्तनशील रहना चाहिए, और बदल सकता है, इसलिए मैं एक विधि प्रदान नहीं कर सकता __hash__()। यदि यह ऐसा करने का एकमात्र तरीका है, तो मैं अपरिवर्तनीय Itemएस के उपयोग के लिए फिर से लिखूंगा ।


1
यही समस्या थी। मुझे लगता है कि आप अपने कोड के अंदर डेटा की छोटी मात्रा में हेरफेर कर रहे हैं। यह संभवतः डेटाबेस के उपयोग के लिए एक अच्छा उम्मीदवार नहीं है। मुझे याद है कि मैं एक सेट बनाने और C ++ में एक तुलनित्र फ़ंक्शन को परिभाषित करने में सक्षम हूं और मुझे जावा पर भी विश्वास है, हालांकि ऐसा नहीं लगता है कि आप पायथन में शब्दकोश वस्तुओं के साथ ऐसा कर सकते हैं। लगता है जैसे किसी ने अजगर में "सेट" लाइब्रेरी लिखी हो जो ऐसा कर सकती है, लेकिन मुझे एक के बारे में पता नहीं है।
क्रिस डुट्रो

जवाबों:


32

मुझे डर है कि आपको एक __hash__()विधि प्रदान करनी होगी । लेकिन आप इसे इस तरह से कोडित कर सकते हैं, कि यह आप की परस्पर विशेषताओं पर निर्भर न हो Item


3
< docs.python.org/reference/… > यहां दूसरे पैराग्राफ में, यह इंगित करता है कि __hash__()केवल अपरिवर्तनीय वस्तुओं के लिए परिभाषित किया जाना चाहिए।
आदा

1
@ नथनेल: यदि वस्तु को बदलना पड़ सकता है, तो आप वस्तु की अपरिवर्तनीय प्रतिलिपि बना सकते हैं, जैसे कि फ्रेज़ेनसेट () और सेट ()।
रयान

2
@ नथनेल - आप कैसे कॉल करना चाहेंगे __eq__? उन (1,2) विशेषताओं की तुलना? फिर आपको अपनी __hash__विधि में कुछ (1,2) हैश लौटना होगा ।
यूमिरो

या, चूंकि फू और बार दोनों अपरिवर्तनीय हैं, __hash __ () फू और बार के हैश का योग लौटा सकता है? नहीं ... राशि बहुत अधिक अविश्वसनीय है ... यदि फू 1 और बार 2 है, तो 1 के रूप में 2 के साथ फू के बराबर बार होगा, जो गलत है। इस उद्देश्य के लिए कौन से गणितीय कार्य का उपयोग किया जा सकता है? मोडुलो या डिवीजन को काम करना चाहिए।
आद्या

1
नथनेल: बस hashबिल्टिन का उपयोग करें hash((self.foo, self.bar)):। यह टपल के हैश का उपयोग करता है, जो आपकी आवश्यकताओं के लिए उपयुक्त है। (आपकी तुलना के __eq__संदर्भ में भी लिखा जा सकता है tuple।)
Pi Delport

76

हां, आपको एक __hash__()एमथोड और तुलना-संचालक की आवश्यकता है जो आपने पहले ही प्रदान किया है।

class Item(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    def __repr__(self):
        return "Item(%s, %s)" % (self.foo, self.bar)
    def __eq__(self, other):
        if isinstance(other, Item):
            return ((self.foo == other.foo) and (self.bar == other.bar))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    def __hash__(self):
        return hash(self.__repr__())

3
अजगर 3 पर, आपको ज़रूरत नहीं है __ne__, और यहां तक ​​कि 2.x में, आपको के __ne__संदर्भ में परिभाषित नहीं करना चाहिए __eq__। देखें, stackoverflow.com/a/30676267/5337834
जॉन स्ट्रॉड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.