2011-09-26 17 views
9

contains__ __contains__ प्रलेखनअप्रत्याशित व्यवहार .__

print set.__contains__.__doc__ 
x.__contains__(y) <==> y in x. 

इस तरह के पूर्णांक, basestring, आदि के रूप लेकिन उपयोगकर्ता परिभाषित वस्तुओं कि __ne__ परिभाषित के लिए आदिम वस्तुओं के लिए ठीक से काम करने लगता है से प्रलेखन उधार और __eq__ विधियों, मुझे अप्रत्याशित व्यवहार मिलता है। यहां एक नमूना कोड है:

class CA(object): 
    def __init__(self,name): 
    self.name = name 

    def __eq__(self,other): 
    if self.name == other.name: 
     return True 
    return False 

    def __ne__(self,other): 
    return not self.__eq__(other) 

obj1 = CA('hello') 
obj2 = CA('hello') 

theList = [obj1,] 
theSet = set(theList) 

# Test 1: list 
print (obj2 in theList) # return True 

# Test 2: set weird 
print (obj2 in theSet) # return False unexpected 

# Test 3: iterating over the set 
found = False 
for x in theSet: 
    if x == obj2: 
    found = True 

print found # return True 

# Test 4: Typcasting the set to a list 
print (obj2 in list(theSet)) # return True 

तो क्या यह एक बग या सुविधा है?

+0

इस सवाल का होना चाहिए यहां स्टैक ओवरफ्लो पर प्रदर्शित होने पर: ** प्रश्न पूछने के लिए **। समस्या को चित्रित करने वाले एक छोटे से उदाहरण के साथ, बिंदु को स्पष्ट करें। जैसा कि अन्य ने यहां उत्तर दिया है, हैश मानों का उपयोग करता है या नहीं तो उन्हें सूचियों का पूर्वाग्रह मिलेगा .. – bjarneh

+0

स्टाइल नोट: 'if cond' के बजाय 'return self.name == other.name' का उपयोग करें: वापस लौटें \ n वापसी गलत है ' – jfs

उत्तर

2

setहैश यह तेज़ लुकअप की अनुमति देने के लिए तत्व हैं।

class CA(object): 
    def __hash__(self): 
    return hash(self.name) 

सूचियाँ हैशिंग का उपयोग नहीं करते हैं, लेकिन की तरह अपने for पाश करता है प्रत्येक तत्व की तुलना: आप __hash__ विधि अधिलेखित करने के लिए इतना है कि एक तत्व पाया जा सकता है है।

3

इसका कारण यह है CA__hash__

को लागू नहीं करता है एक समझदार कार्यान्वयन होगा:

def __hash__(self): 
    return hash(self.name) 
7

set और dicts के लिए, आप __hash__ परिभाषित करने की जरूरत। set एस और dicts में लगातार/अपेक्षित व्यवहार प्राप्त करने के लिए समान रूप से किसी भी दो ऑब्जेक्ट्स को समान होना चाहिए।

मैं एक _key विधि का उपयोग कर की सिफारिश करेंगे, और फिर बस को संदर्भित कि कहीं भी आप आइटम की तुलना करने के भाग की जरूरत है, बस के रूप में आप __eq____neq__ से यह reimplementing के बजाय फोन:

class CA(object): 
    def __init__(self,name): 
    self.name = name 

    def _key(self): 
    return type(self), self.name 

    def __hash__(self): 
    return hash(self._key()) 

    def __eq__(self,other): 
    if self._key() == other._key(): 
     return True 
    return False 

    def __ne__(self,other): 
    return not self.__eq__(other) 
संबंधित मुद्दे