2013-11-26 11 views
6

शामिल मैं अजगर 2.7अजगर सेट होता है बनाम सूची

उपयोग कर रहा हूँ

निम्नलिखित स्निपेट पर विचार (उदाहरण के काल्पनिक है):

import datetime 

class ScheduleData: 
    def __init__(self, date): 
     self.date = date 

    def __eq__(self, other): 
     try: 
      return self.date == other.date 
     except AttributeError as e: 
      return self.date == other 

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



schedule_set = set() 
schedule_set.add(ScheduleData(datetime.date(2010, 8, 7))) 
schedule_set.add(ScheduleData(datetime.date(2010, 8, 8))) 
schedule_set.add(ScheduleData(datetime.date(2010, 8, 9))) 

print (datetime.date(2010, 8, 8) in schedule_set) 

schedule_list = list(schedule_set) 

print (datetime.date(2010, 8, 8) in schedule_list) 

इस से निर्गम (मेरे लिए अप्रत्याशित है, कम से कम) पर:

[08:02 PM toolscripts]$ python test.py 
True 
False 
पहले मामले में

, दी गई तारीख schedule_set में पाया जाता है के रूप में मैं __hash__ और __eq__ कार्यों अधिरोहित है।

मेरी समझ से in ऑपरेटर सेट के लिए हैश और समानता के खिलाफ जांच करेगा, लेकिन सूचियों के लिए यह सूची में आइटमों को आसानी से फिर से चालू करेगा और समानता की जांच करेगा।

तो यहां क्या हो रहा है? schedule_list सूची में in के लिए मेरा दूसरा परीक्षण क्यों विफल हो गया है?

क्या मुझे सूचियों के लिए कुछ अन्य फ़ंक्शन ओवरराइड करना है?

+0

मेरे लिए काम करता है .. पायथन 3.3 मुझे आश्चर्य है क्यों। पुष्टि की, यह पायथन 2.7 – aIKid

+0

पर काम नहीं करता है, साथ ही '__neq__' जोड़ने का प्रयास करें। – tacaswell

+0

@tcaswell, धन्यवाद, मैंने पहले से ही कोशिश की है और इसका उल्लेख किया जाना चाहिए था, लेकिन यह काम नहीं करता - उन '__ne__', '__neq__' और' __eq__' कार्यों को दूसरे मामले में नहीं कहा जाता है। – randomfigure

उत्तर

8

समस्या यह है कि तुलना आप जो देख रहे हैं उसके विपरीत __eq__ फ़ंक्शन का आविष्कार कर रही है। __eq__ विधि परिभाषित होती है जब आपके पास ScheduleData() == datetime.date() है लेकिन in ऑपरेटर विपरीत क्रम में तुलना कर रहा है, datetime.date() == ScheduleData() जो आपके परिभाषित __eq__ का आविष्कार नहीं कर रहा है। बाएं हाथ की ओर के रूप में कार्य करने वाली कक्षा केवल __eq__ कहलाएगी।

यह समस्या पाइथन 2 में होती है और 3 को std लाइब्रेरी में datetime.date.__eq__ की परिभाषा के साथ नहीं करना है। उदाहरण के लिए ले लो निम्नलिखित दो वर्गों:

class A(object): 
    def __eq__(self, other): 
     print ('A.__eq__') 
     return False 

class B(object): 
    def __eq__(self, other): 
     print ('B.__eq__') 

items = [A()] 
B() in items 

दोनों अजगर 2 और अजगर 3. B वस्तु एलएचएस के रूप में प्रयोग किया जाता है के तहत इस कोड प्रिंट B.__eq__ चल रहा है, बस के रूप में अपने datetime.date वस्तु अजगर 2 में प्रयोग किया जाता है हालांकि, अगर मैं B.__eq__ को फिर से परिभाषित datetime.date.__eq__ का अजगर 3 defintion सदृश:

class B(object): 
    def __eq__(self, other): 
     print ('First B.__eq__') 
     if isinstance(self, other.__class__): 
      print ('B.__eq__') 
     return NotImplemented 

तब:

First B.__eq__ 
A.__eq__ 

दोनों पायथन 2 और 3 के तहत मुद्रित है। NotImplemented की वापसी का कारण तर्कों के साथ चेक को उलट देता है।

अपनी कक्षा में timetuple का उपयोग करते हुए इस समस्या को हालांकि ऐसा लगता है कि यह एक समारोह

class ScheduleData: 
    timetuple = None 

होने की जरूरत नहीं, के रूप में @TimPeters कहा (दिलचस्प मोड़ मैं अनजान था), ठीक कर देंगे आप सभी की जरूरत होता है आपके पास पहले से ही क्या है।

+0

मैं जोड़ता हूं कि इस मामले में व्यवहार तुलनात्मक प्रकार के रूप में 'datetime.date' के उपयोग पर निर्भर करता है। यदि आप पास करते हैं, उदाहरण के लिए, "दिनांक" मान के रूप में एक int या स्ट्रिंग, वही कक्षा ठीक काम करती है। तो समस्या यह भी है क्योंकि 'datetime.date' में अंतर्निहित दोनों-पक्ष-तुलनात्मक व्यवहार नहीं हैं जो बिल्टिन प्रकार के रूप में हैं। – BrenBarn

+0

@ ब्रेनबर्न मुझे इस पर संदेह है कि मैं अभी लाइब्रेरी कोड देख रहा हूं –

6

@RyanHaining सही है। वास्तव में एक विचित्र वैकल्पिक हल के लिए, अपने वर्ग के लिए इस पद्धति जोड़ें:

def timetuple(self): 
    return None 

फिर अपने कार्यक्रम True दो बार प्रिंट होगा।इसके लिए कारण शामिल हैं, पाइथन 2 में तुलना के दुर्भाग्यपूर्ण इतिहास के साथ बहुत ढीला होना है। timetuple() वैकल्पिक हल ज्यादातर डॉक्स के इस हिस्से में समझाया गया है:

नोट आदेश की तुलना वस्तु पतों की डिफ़ॉल्ट योजना, दिनांक पर वापस गिरने से तुलना रोकने के लिए तुलना सामान्य रूप से करता है, तो अन्य comparand isn लेखन त्रुटि को जन्म देती है एक डेटाटाइम ऑब्जेक्ट भी नहीं है। हालांकि, विशेषता नहीं है अगर अन्य तुलना में एक timetuple() विशेषता है। यह हुक अन्य प्रकार की तारीख वस्तुओं को मिश्रित प्रकार की तुलना लागू करने का मौका देता है। यदि नहीं, जब किसी डेटाटाइम ऑब्जेक्ट की तुलना के किसी ऑब्जेक्ट से की जाती है, तो टाइपरर तब तक उठाया जाता है जब तक तुलना == या! = है। बाद के मामले क्रमशः झूठी या सही, लौटते हैं।

datetime पाइथन में जोड़े गए पहले प्रकारों में से एक था जिसने कम आश्चर्यजनक तुलना व्यवहार की पेशकश करने की कोशिश की। लेकिन, यह पाइथन 3 तक "वास्तव में साफ" नहीं हो सका।

+0

धन्यवाद समय, मैंने रायन के जवाब को स्वीकार किया, लेकिन आपका उतना ही सहायक है। – randomfigure

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