2016-05-10 6 views
16

पायथन x > y > z जैसे अभिव्यक्तियों की अनुमति देता है, जो दस्तावेज़ों के अनुसार (x > y) and (y > z) के बराबर है y को छोड़कर केवल एक बार मूल्यांकन किया जाता है। (https://docs.python.org/3/reference/expressions.html)कस्टम जंजीर तुलना

हालांकि, अगर मैं तुलनात्मक कार्यों को कस्टमाइज़ करता हूं तो यह तोड़ने लगता है। जैसे मैं निम्नलिखित वर्ग है लगता है: (। बड़े ब्लॉक के लिए क्षमा याचना, लेकिन एक बार आप __eq__ विधि पढ़ा है, बाकी मामूली बात है)

class CompareList(list): 
    def __repr__(self): 
     return "CompareList([" + ",".join(str(x) for x in self) + "])" 

    def __eq__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] == other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x == other for x in self) 

    def __ne__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] != other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x != other for x in self) 

    def __gt__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] > other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x > other for x in self) 

    def __ge__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] >= other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x >= other for x in self) 

    def __lt__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] < other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x < other for x in self) 

    def __le__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] <= other[idx] for idx in xrange(len(self))) 
     else: 
      return CompareList(x <= other for x in self) 

अब मैं CompareList([10, 5]) > CompareList([5, 10]) की मज़ेदार बातों से कर सकते हैं और इसे सही ढंग CompareList([True,False])

वापस आ जाएगी

हालांकि, इन कार्यों के चेनिंग अच्छी तरह से काम नहीं करता है:

low = CompareList([1]) 
high = CompareList([2]) 
print(low > high > low) # returns CompareList([True]) 

क्यों नहीं? हुड के नीचे क्या होता है? मुझे पता है कि यह (low > high) > low = (False > low) के बराबर नहीं है (क्योंकि वह झूठी वापसी करेगा)। यह low > (high > low) हो सकता है लेकिन यह ऑपरेटर प्राथमिकता (आमतौर पर बाएं से दाएं) के मामले में समझ में नहीं आता है।

+1

चेक बाहर 'functools.total_ordering' - अगर मैं सही ढंग से याद करते हैं, आप केवल एक सीएमपी जैसे' __eq__' और एक आदेश, जैसे '__lt__' आपूर्ति और' ** कक्षा में जोड़ें @ functools.total_ordering' करने की जरूरत है **, और यह आपके लिए बाकी को भरना चाहिए। – dwanderson

+0

@ ड्वांडरसन मुझे याद है कि पाइथन आपके लिए बाकी करेगा। –

उत्तर

8

अजगर की अनुमति देता है x > y > z की तरह भाव है, जो, डॉक्स के अनुसार, y छोड़कर (x > y) and (y > z) के बराबर है केवल एक बार मूल्यांकन किया जाता है।

इसके अनुसार, low > high > low(low > high) and (high > low) के बराबर होगा।

x and y: x and y पर दस्तावेज़ीकरण से

>>> x = low > high # CompareList([False]) 
>>> y = high > low # CompareList([True]) 
>>> x and y 
CompareList([True]) 

अधिक अगर x, बाकी y

झूठी, तो x है ऊपर मामले में:

>>> x is False 
False 
>>> x if x is False else y  # x and y 
CompareList([True]) 

इसलिए जब आप x and y करते हैं तो यह y देता है जो CompareList([True]) है।

+1

वह ... एक आश्चर्यजनक सरल जवाब है! – acdr

+1

यह नहीं होना चाहिए कि "अगर' x' गलत है "कोड के साथ या तो 'x' या' अगर बूल (x) गलत है? उदाहरण के लिए '' 'और ट्रू' '' '' ''' के बावजूद '' 'बदलेगा' झूठा नहीं है '। इस मुद्दे का एक हिस्सा यह है कि 'bool (custom_object)' 'True' वापस लौटाएगा जब तक कि' __nonzero__' ओवरराइड नहीं हो जाता है, लेकिन ओपी के इरादे से फ़िल्टर करने के तरीके को फ़िल्टर करना असंभव है, जैसा कि @ iulian के उत्तर में उल्लेख किया गया है। –

+0

''' और ट्रू 'रिटर्न' '' 'क्योंकि' 'बूल (' ')'] (https://docs.python.org/3/library/stdtypes.html#truth-value-testing)' झूठा है '। इसलिए यदि आप तर्क '' 'से जाते हैं, तो' 'गलत है तो सत्य' '' 'गलत है' सत्य 'का मूल्यांकन करता है और आपको '' 'मिलता है। – AKS

1

आपको अपनी तुलना विधियों से एक बूलियन मान वापस करना चाहिए।

का हवाला देते हैं करने के लिए documentation for "rich comparison" methods:

परंपरा के मुताबिक, झूठी और यह सच है एक सफल तुलना के लिए चुना जाता है। हालांकि, ये विधियां किसी भी मान को वापस कर सकती हैं, इसलिए यदि तुलना ऑपरेटर को बूलियन संदर्भ में उपयोग किया जाता है (उदाहरण के लिए, किसी कथन की स्थिति में), पायथन पर मान पर बूल() को कॉल करेगा, यह निर्धारित करने के लिए कि क्या परिणाम है सही या गलत।

इस मामले के लिए इसे नीचे तोड़ने के लिए:

exp1 = low > high 
print(exp1) 
print(bool(exp1)) 
exp2 = high > low 
print(exp2) 
print(bool(exp2)) 

आप

CompareList([False]) 
True 
CompareList([True]) 
True 

अब देंगे हम पिछले आपरेशन करते हैं और परिणाम प्रिंट आउट

print(exp1 and exp2) 

क्योंकि दोनों मान True का मूल्यांकन करेंगे जो आपको मिलेगा

CompareList([True]) 
+0

मुझे नहीं लगता कि तुलनात्मक तुलना करने के सवाल के लिए इसकी प्रासंगिकता कैसे है। मुझे पता है कि 'अगर तुलना सूची ([सही, गलत]):' समझ में नहीं आता है। – acdr

+0

मैंने कुछ और स्पष्टीकरण जोड़े। – Matthias

3

अन्य उत्तर सही हैं, लेकिन मैं, इस समस्या के लिए कार्यान्वयन की वास्तविक कमी को संबोधित करने के लिए, क्योंकि के रूप में मेरा मानना ​​है कि, क्या ओपी low > high > low से एक परिणाम के रूप प्राप्त करना चाहते हैं एक CompareList([False]) है चाहता था।

दरअसल, low > high > low(low > high) and (high > low) को मूल्यांकन करता है और के बाद से CompareList([False]) is FalseFalse का मूल्यांकन (जिसका अर्थ है कि यह True है), तो and ऑपरेटर के दूसरे संकार्य का मूल्यांकन किया और वापस आ जाता है (के रूप में यह भी True का मूल्यांकन)।

जंजीर तुलना को लागू करने की कुंजी and बूलियन ऑपरेटर को __gt__ और __lt__ के साथ ओवरराइड करना है।

दुर्भाग्यवश, ऐसा करने का कोई तरीका नहीं है, और शायद नहीं होगा। PEP 335 - Overloadable Boolean Operators proposal को गिडो द्वारा खारिज कर दिया गया था, लेकिन वह < बी < सी अधिभार योग्य [1] जैसे जंजीर तुलना करने पर विचार कर सकता है।

उस पल तक, जब तक जंजीर तुलना का उपयोग करते समय अपेक्षित काम करने के लिए आपका उदाहरण प्राप्त करने का कोई तरीका नहीं है।

सही परिणाम प्राप्त करने के लिए एक ही रास्ता __and__ विधि अधिभावी और इस तरह से अपनी तुलना लिख ​​कर है: तो फिर

def CompareList(list): 
    ... 
    def __and__(self, other): 
     if isinstance(other, list): 
      return CompareList(self[idx] and other[idx] for idx in range(len(self))) 
     else: 
      return CompareList(x and other for x in self) 

, नीचे दिए गए फॉर्म में लिख कर, आप सही उत्तर मिल जाएगा:

low = CompareList([1, 2]) 
high = CompareList([2, 2]) 
print((low >= high) & (high >= low)) # returns CompareList([False, True]) 
+0

यह सुनिश्चित नहीं है कि यह उच्च क्यों नहीं है, बहुत अंतर्दृष्टिपूर्ण, खासकर पीईपी संदर्भ। मैं ध्यान दूंगा कि 'तुलनासूची ([झूठा]) गलत है, शायद इसे' बूल में बदल दिया जाना चाहिए (तुलनासूची ([झूठी])) गलत है क्योंकि इसकी सच्चाई की जांच की जा रही है, इसकी पहचान नहीं। –

+0

@JaredGoguen धन्यवाद! मैंने अन्य उत्तरों पोस्ट किए जाने के 1 घंटे बाद इसे पोस्ट कर दिया है, इसलिए यही कारण है कि ... – iulian

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