एक अजगर उपयोगकर्ता-परिभाषित वर्ग को छांटने योग्य, धोने योग्य बनाना


83

अजगर में उपयोगकर्ता-परिभाषित वर्गों को क्रमबद्ध और / या हैज़ेबल बनाते समय किन तरीकों को ओवरराइड / कार्यान्वित किया जाना चाहिए?

बाहर देखने के लिए क्या कर रहे हैं?

मैं dir({})अंतर्निहित दुभाषियों पर विधियों की एक सूची प्राप्त करने के लिए अपने दुभाषिया में टाइप करता हूँ। उनमें से, मुझे लगता है कि मुझे कुछ के कुछ सबसेट को लागू करने की आवश्यकता है

['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']

क्या पायथन 2 के विपरीत पायथन 3 के लिए किन तरीकों को लागू किया जाना चाहिए, इसमें अंतर है?


3
अच्छा चर्चा यहाँ: stackoverflow.com/q/1061283/641766 । पायथन 2.x और 3.x के बीच का अंतर यह है कि __cmp__हटा दिया गया था।
zeekay

जवाबों:


90

मैंने इसे लगभग अन्य उत्तरों के लिए एक टिप्पणी के रूप में पोस्ट किया है, लेकिन यह वास्तव में और अपने आप में एक उत्तर है।

अपनी वस्तुओं को क्रमबद्ध बनाने के लिए, उन्हें केवल कार्यान्वित करना होगा __lt__। यह एकमात्र तरीका है जो बिल्ट द्वारा बनाया गया है।

functools.total_orderingयदि आप वास्तव में अपनी कक्षा के साथ तुलना संचालकों का उपयोग करना चाहते हैं तो अन्य तुलना या केवल आवश्यक हैं।

अपनी वस्तुओं को धोने योग्य बनाने के लिए, आप __hash__अन्य लोगों के रूप में नोट करते हैं। आपको __eq__एक सुसंगत तरीके से भी लागू करना चाहिए - जो आइटम समतुल्य हैं उनके पास हैश होना चाहिए।


इसलिए __lt__अजगर के खराब कार्यान्वयन से अप्रत्याशित रूप से छंटनी हो सकती है? (उदाहरण के लिए, अगर x .__ lt __ (y) और y .__ lt __ (x))
मैट फेनविक

3
मैं "अप्रत्याशित रूप से" के बारे में नहीं जानता, अगर यह एक ही इनपुट खिलाया जाता है तो यह सुसंगत होगा, लेकिन एक अलग इनपुट ऑर्डर के कारण अलग-अलग आइटम अलग ऑर्डर में हो सकते हैं। हां, यदि आप छँटनी के लिए इस्तेमाल की गई तुलना को अनुचित तरीके से लागू करते हैं, तो पायथन अनुचित तरीके से छँटेगा। मैं एक ऐसे __key__फंक्शन की सलाह दूंगा, जो इंस्टेंस को टूपल में बदल दे, तो बस दोनों __lt__( self.__key__() < other.__key__()) और __hash__( hash(self.__key__())) का उपयोग करें।
एजीएफ़

21

पायथन 2 और 3 में कोई अंतर नहीं है।

छँटाई के लिए:

आपको तुलनात्मक तरीकों को परिभाषित करना चाहिए। यह आपके आइटम को क्रमबद्ध बनाता है। आम तौर पर, आपको पसंद नहीं करना चाहिए __cmp__()

मैं आमतौर पर configools.total_ordering डेकोरेटर का उपयोग करता हूं।

functionalools.total_ordering (cls) एक या एक से अधिक समृद्ध तुलना आदेश विधियों को परिभाषित करने वाले वर्ग को देखते हुए, यह वर्ग सज्जाकार बाकी की आपूर्ति करता है। यह संभव समृद्ध तुलनात्मक संचालन के सभी को निर्दिष्ट करने में शामिल प्रयास को सरल बनाता है:

वर्ग में से एक को परिभाषित करना होगा __lt__(), __le__(), __gt__(), या __ge__()। इसके अलावा, वर्ग को एक __eq__()विधि की आपूर्ति करनी चाहिए ।

आपको सावधान रहना चाहिए कि आपकी तुलना के तरीकों का कोई दुष्प्रभाव नहीं है। (वस्तु के किसी भी मूल्य को बदलें)

हैशिंग के लिए:

आपको __hash__()विधि लागू करनी चाहिए । मुझे लगता है कि सबसे अच्छा तरीका लौट रहा है hash(repr(self)), इसलिए आपका हैश अद्वितीय होगा।


functools.total_orderingप्रलेखन से एक उदाहरण के लिए , यहां देखें ।
एवगेनी सर्गेव

3

अपनी वस्तु को छांटने के कुछ तरीके हैं। पहला - समृद्ध तुलना, कार्यों के एक समूह द्वारा परिभाषित:

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

इसके अलावा केवल एक फ़ंक्शन को परिभाषित करना संभव है:

object.__cmp__(self, other)

और अंतिम परिभाषित किया जाना चाहिए यदि आप कस्टम __hash__फ़ंक्शन को परिभाषित करना चाहते हैं । डॉक्टर को देखें ।


6
पायथन 3 में, "[...] __cmp__()विशेष विधि अब समर्थित नहीं है," संबंधित अनुभाग यहां देखें
एवगेनी सर्गेव

-3

कार्यान्वयन __lt__(self,other)विधि आपके वर्ग को क्रमबद्ध बनाने का उत्तर है।
यह न केवल अंतर्निहित पद्धति के लिए उपयोग किया जा सकता है sorted(iterable), बल्कि heapqमॉड्यूल के माध्यम से प्राथमिकता कतार भी है ।

इसके अलावा, मुझे अजगर का डिज़ाइन पसंद नहीं है, इसलिए कई '__ge__', '__gt__', '__le__', '__lt__', '__ne__'तरीके बिल्कुल सहज नहीं हैं !
इसके विपरीत, जावा का Interface Comparable<T> ( जावा डॉवा देखें ) एक नकारात्मक पूर्णांक, शून्य, या एक सकारात्मक पूर्णांक देता है क्योंकि यह वस्तु निर्दिष्ट वस्तु से कम, बराबर या उससे अधिक है, जो प्रत्यक्ष और अनुकूल है !


9
आपका अधिकांश उत्तर आपकी राय को कवर करता है (जो उत्तर का हिस्सा नहीं होना चाहिए)।
skyking

@ स्कीइंग ... जबकि मैं इस विशेष उत्तर में राय से सहमत नहीं हूं, मेरा मानना ​​है कि राय (प्रश्न के लिए प्रासंगिक अनुसंधान और उपयोगी डेटा के साथ) बहुत मूल्यवान है। इस राय उत्तर में त्रुटि प्रासंगिक डेटा के साथ राय का समर्थन नहीं कर रही है। लेकिन वरीयताओं को समझना लोगों को निर्णय लेने में मदद करता है और इसलिए यह बहुत उपयोगी है। यहाँ, उत्तर बीमार है क्योंकि लेखक की वरीयताओं के आधार पर एक पायथोनिक कोड को दर्शाने के लिए कोई उपयोगी और क्रियात्मक अजगर कोड नहीं है।
एंड्रयू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.