अजगर वर्ग को वस्तु विरासत में मिलती है


1240

क्या कोई वर्ग घोषणा से विरासत में लेने का कोई कारण है object?

मुझे बस कुछ कोड मिले जो ऐसा करता है और मुझे एक अच्छा कारण नहीं मिल सकता है।

class MyClass(object):
    # class code follows...

2
यह एक नई शैली की क्लास बनाता है ।
SLACs

115
इस सवाल का जवाब (जबकि सरल) खोजने में काफी मुश्किल है। "अजगर ऑब्जेक्ट बेस क्लास" या इसी तरह की चीजों को देखने से ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग पर पेज और ट्यूटोरियल के पेज मिलते हैं। Upvoting क्योंकि यह पहली कड़ी है जिसने मुझे खोज शब्द "पुरानी बनाम नई शैली के पायथन ऑब्जेक्ट्स" की ओर
अग्रसर किया

जवाबों:


762

क्या कोई वर्ग घोषणा से विरासत में लेने का कोई कारण है object?

पायथन 3 में, पायथन 2 और 3 के बीच संगतता के अलावा, कोई कारण नहीं । पायथन 2 में, कई कारण


पायथन 2.x कहानी:

पायथन 2.x में (2.2 से आगे) objectएक बेस-क्लास के रूप में उपस्थिति या अनुपस्थिति के आधार पर कक्षाओं की दो शैलियाँ हैं :

  1. "क्लासिक" शैली वर्ग: उनके पास objectबेस क्लास के रूप में नहीं है :

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. "नई" शैली की कक्षाएं: उनके पास प्रत्यक्ष या अप्रत्यक्ष रूप से (जैसे अंतर्निहित प्रकार से विरासत में ), objectआधार वर्ग के रूप में:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)
    

एक शक के बिना, जब आप एक क्लास लिखते हैं तो आप हमेशा नई शैली की कक्षाओं के लिए जाना चाहेंगे। ऐसा करने के कई गुण हैं, उनमें से कुछ को सूचीबद्ध करने के लिए:

  • वर्णनकर्ताओं के लिए समर्थन । विशेष रूप से, निम्नलिखित निर्माण विवरणकों के साथ संभव किए गए हैं:

    1. classmethod: एक विधि जो वर्ग को उदाहरण के बजाय एक अंतर्निहित तर्क के रूप में प्राप्त करती है।
    2. staticmethod: एक विधि जो selfपहले तर्क के रूप में निहित तर्क को प्राप्त नहीं करती है।
    3. गुण property: किसी विशेषता को प्राप्त करने, स्थापित करने और हटाने के प्रबंधन के लिए कार्य बनाएँ।
    4. __slots__: एक वर्ग की मेमोरी खपत को बचाता है और इसके परिणामस्वरूप तेजी से विशेषता का उपयोग होता है। बेशक, यह सीमाओं को लागू करता है ।
  • __new__स्थिर विधि: आप अनुकूलित कैसे नया वर्ग उदाहरणों बनाई गई हैं देता है।

  • विधि रिज़ॉल्यूशन ऑर्डर (एमआरओ) : किस क्रम में किसी क्लास के बेस क्लासेस को खोजा जाएगा कि किस विधि को कॉल करने की कोशिश की जाए।

  • एमआरओ, superकॉल से संबंधित । इसे भी देखें, super()सुपर माना जाता है।

यदि आपको विरासत में नहीं मिली है object, तो इन्हें भूल जाइए। "नई" शैली वर्गों के अन्य भत्तों के साथ पिछली बुलेट बिंदुओं का अधिक विस्तृत विवरण यहां पाया जा सकता है

नई शैली की कक्षाओं के डाउनसाइड्स में से एक यह है कि वर्ग स्वयं अधिक मेमोरी की मांग कर रहा है। जब तक आप कई क्लास ऑब्जेक्ट नहीं बना रहे हैं, हालांकि, मुझे संदेह है कि यह एक मुद्दा होगा और यह सकारात्मकता के समुद्र में एक नकारात्मक डूब रहा है।


अजगर 3.x कहानी:

पायथन 3 में, चीजें सरल होती हैं। केवल नई-शैली की कक्षाएं मौजूद हैं (स्पष्ट रूप से कक्षाओं के रूप में संदर्भित) इसलिए, जोड़ने में एकमात्र अंतर objectआपको 8 और वर्णों में टाइप करने की आवश्यकता है। इस:

class ClassicSpam:
    pass

पूरी तरह से समतुल्य है (उनके नाम के अलावा :-) इसके लिए:

class NewSpam(object):
     pass

और इसके लिए:

class Spam():
    pass

सब objectअपने में है __bases__

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

तो आपको क्या करना चाहिए?

पायथन 2 में: हमेशा objectस्पष्ट रूप से विरासत में मिलता है । भत्तों को प्राप्त करें।

पाइथन 3 में:object यदि आप ऐसा कोड लिख रहे हैं, जो पैथॉन अज्ञेय होने की कोशिश करता है, तो उससे विरासत में मिला है , अर्थात उसे पायथन 2 और पायथन 3 दोनों में काम करने की आवश्यकता है। अन्यथा नहीं, यह वास्तव में कोई फर्क नहीं पड़ता क्योंकि पायथन आपके लिए इसे लागू करता है। परदे के पीछे।


"बेस-क्लास के रूप में एक अंतर्निहित प्रकार की उपस्थिति या अनुपस्थिति पर निर्भर करता है" => वास्तव में यह "बेस क्लास के रूप में एक बेसिन प्रकार की अनुपस्थिति या उपस्थिति" के बारे में नहीं है, लेकिन वर्ग विरासत - प्रत्यक्ष या अप्रत्यक्ष रूप से - का ध्यान रखें object। IIRC उस समय में एक बिंदु था जहां सभी बिलियन प्रकार नहीं थे जहां अभी तक नई शैली की कक्षाओं के लिए पोर्ट किया गया था।
ब्रूनो डेथिलियर्स

@brunodesthuilliers मेरी धारणा थी कि सभी अंतर्निहित प्रकारों से विरासत में मिला था object। मेरे पास एक पाइथन 2.2.3 है जिसके आसपास और एक त्वरित जांच के बाद मुझे कोई अपराधी नहीं मिला लेकिन, मैं बाद में और स्पष्ट करने के लिए उत्तर दूंगा। रुचि होगी यदि आप एक उदाहरण मिल सकता है, हालांकि, मेरी जिज्ञासा शांत है।
दिमित्रिस फासरकिस हिलियार

सभी ईमानदारी में (मेरी पिछली टिप्पणी में "IIRC") मैं इस बिंदु के बारे में 101% निश्चित नहीं हूं (सभी अंतर्निहित प्रकार पहले से ही नई शैली की कक्षाओं में परिवर्तित हो गए थे जब नई शैली की कक्षाएं शुरू की गई थीं) - मैं सिर्फ सादा हो सकता हूं गलत है, या यह केवल कुछ मानक लिबास (लेकिन बिलियन नहीं) प्रकारों से संबंधित हो सकता है। लेकिन फिर भी मुझे लगता है कि यह स्पष्ट करना बेहतर होना चाहिए कि एक नई शैली का वर्ग जो बनाता है object, उसमें आधार है।
ब्रूनो डेथिलियर्स

7
बहुत बुरा स्टैक्वेरफ़्लो केवल इन थोड़े उत्तरों के लिए upvote = upvote + 1 का काम करता है, काश मैं upvote + = N
PirateApp

1
staticmethodऔर classmethodपुरानी शैली की कक्षाओं पर भी ठीक काम करते हैं। propertyसॉर्टा पुरानी-शैली की कक्षाओं पर पढ़ने के लिए काम करता है , यह सिर्फ लिखने में अवरोधन करने में विफल रहता है (इसलिए यदि आप नाम पर असाइन करते हैं, तो उदाहरण दिए गए नाम की एक विशेषता प्राप्त करता है जो संपत्ति को छाया देता है)। यह भी ध्यान दें कि __slots__विशेषता पहुंच की गति में सुधार ज्यादातर नुकसान के बारे में है कि नई-शैली वर्ग विशेषता पहुंच को नुकसान पहुंचाता है, इसलिए यह वास्तव में नई शैली की कक्षाओं का विक्रय बिंदु नहीं है (स्मृति बचत हालांकि एक विक्रय बिंदु है)।
शैडो रेंजर

540

अजगर ३

  • class MyClass(object): = नई शैली की कक्षा
  • class MyClass:= नई शैली की कक्षा (स्पष्ट रूप से विरासत में मिली object)

अजगर २

  • class MyClass(object): = नई शैली की कक्षा
  • class MyClass:= पुराने स्टाइल वर्ग

स्पष्टीकरण :

पायथन 3.x में आधार कक्षाओं को परिभाषित करते समय, आपको objectपरिभाषा से छोड़ने की अनुमति है । हालांकि, यह समस्या को ट्रैक करने के लिए एक गंभीर मुश्किल के लिए दरवाजा खोल सकता है ...

पायथन ने पायथन 2.2 में नई शैली की कक्षाएं शुरू कीं, और अब तक पुरानी शैली की कक्षाएं वास्तव में काफी पुरानी हैं। पुरानी शैली की कक्षाओं की चर्चा 2.x डॉक्स में और 3.x डॉक्स में गैर-मौजूद है।

समस्या यह है कि, Python 2.x में पुरानी शैली की कक्षाओं के लिए सिंटैक्स, Python 3.x में नई-शैली कक्षाओं के लिए वैकल्पिक सिंटैक्स के समान है । पायथन 2.x अभी भी बहुत व्यापक रूप से उपयोग किया जाता है (जैसे GAE, Web2Py), और किसी भी कोड (या कोडर) को अनजाने में 3.x-शैली वर्ग परिभाषाओं को 2.x कोड में लाना कुछ गंभीर रूप से पुरानी आधार वस्तुओं के साथ समाप्त होने जा रहा है। और क्योंकि पुरानी शैली की कक्षाएं किसी के रडार पर नहीं हैं, इसलिए संभवत: उन्हें पता नहीं होगा कि उन्हें क्या मारा।

तो बस इसे लंबा करें और कुछ 2.x डेवलपर के आँसू बचाएं।


13
"पायथन 3.x में आधार कक्षाओं को परिभाषित करते समय, आपको ऑब्जेक्ट को परिभाषा से छोड़ने की अनुमति दी जाती है। हालाँकि, यह समस्या को ट्रैक करने के लिए एक गंभीर मुश्किल के लिए दरवाजा खोल सकता है ..." आप किन समस्याओं का उल्लेख कर रहे हैं?
ऐडिस

6
@ ऐडिस: मुझे लगता है कि उनका मतलब है कि Py2 और Py3 दोनों पर चलने वाला कोड Py3 पर ठीक होगा, लेकिन Py2 पर तोड़ा जा सकता है अगर यह नई शैली के क्लास फीचर्स पर निर्भर करता है। व्यक्तिगत रूप से, अगर मैं उस तरह का कोड लिख रहा हूं, तो मैं स्पष्ट उत्तराधिकार को छोड़ देता हूं और बस __metaclass__ = typeमॉड्यूल के शीर्ष पर रखा जाता है ( from __future__ import absolute_import, division, print_functionलाइन :-) के बाद ); यह Py2 में एक संगतता हैक है, जो डिफ़ॉल्ट रूप से मॉड्यूल के बाद के सभी वर्गों को नई शैली में परिभाषित करता है, और Py3 में, इसे पूरी तरह से अनदेखा किया जाता है (बस एक यादृच्छिक वैश्विक चर चारों ओर बैठा है), इसलिए यह हानिरहित है।
शैडो रेंजर

400

हाँ, यह एक 'नई शैली' वस्तु है। यह python2.2 में पेश किया गया एक फीचर था।

नई शैली की वस्तुओं में क्लासिक ऑब्जेक्ट के लिए एक अलग ऑब्जेक्ट मॉडल होता है, और कुछ चीजें पुरानी शैली की वस्तुओं के साथ ठीक से काम नहीं करेंगी, उदाहरण के लिए super(), @propertyऔर विवरणकर्ता। एक नई शैली वर्ग क्या है, इसके अच्छे विवरण के लिए इस लेख को देखें ।

मतभेदों के विवरण के लिए SO लिंक: पायथन में पुरानी शैली और नई शैली वर्गों के बीच क्या अंतर है?


110
+1 यह। ध्यान दें कि पुरानी शैली की कक्षाएं पायथन 3 में चली गई हैं, इसलिए आपको केवल objectपायथन 2 से विरासत में प्राप्त करने की आवश्यकता है

9
यह वास्तविक उत्तर नहीं है। मैं सिर्फ अन्य लेखों का संदर्भ देता हूं। मुझे लगता है कि यारिन के उत्तर को इस प्रश्न के उत्तर के रूप में स्वीकार किया जाना चाहिए।
११

2
@alwbtc: इस जवाब में कुछ नया भी है। उदाहरण के लिए "सुपर ()" के उल्लेख ने मुझे एक और महत्वपूर्ण [यहाँ] ( stackoverflow.com/questions/576169/… ) के लिए प्रेरित किया ।
वीआईएफआई

34

लर्न पायथॉन द हार्ड वे से इतिहास :

पायथन का एक वर्ग का मूल प्रतिपादन कई गंभीर तरीकों से टूट गया था। जब तक इस गलती को पहचान लिया गया तब तक यह पहले ही बहुत देर हो चुकी थी, और उन्हें इसका समर्थन करना था। समस्या को ठीक करने के लिए, उन्हें कुछ "नए वर्ग" शैली की आवश्यकता थी ताकि "पुरानी कक्षाएं" काम करती रहें लेकिन आप नए अधिक सही संस्करण का उपयोग कर सकते हैं।

उन्होंने फैसला किया कि वे एक "ऑब्जेक्ट" शब्द का उपयोग करेंगे, जिसे "क्लास" कहा जाएगा, जिसे आप एक क्लास बनाने के लिए विरासत में लेते हैं। यह भ्रामक है, लेकिन एक वर्ग "ऑब्जेक्ट" नामक वर्ग से एक वर्ग बनाने के लिए विरासत में मिला है, लेकिन यह वास्तव में एक वस्तु नहीं है इसका वर्ग है, लेकिन ऑब्जेक्ट से विरासत में प्राप्त करना मत भूलना।

केवल यह बताने के लिए कि नई शैली की कक्षाओं और पुरानी शैली की कक्षाओं के बीच अंतर क्या है, यह है कि नई शैली की कक्षाएं हमेशा objectवर्ग से या किसी अन्य वर्ग से विरासत में मिलती हैं object:

class NewStyle(object):
    pass

एक और उदाहरण है:

class AnotherExampleOfNewStyle(NewStyle):
    pass

जबकि एक पुरानी शैली का आधार वर्ग इस तरह दिखता है:

class OldStyle():
    pass

और एक पुरानी शैली का बच्चा वर्ग इस तरह दिखता है:

class OldStyleSubclass(OldStyle):
    pass

आप देख सकते हैं कि एक पुरानी शैली का आधार वर्ग किसी अन्य वर्ग से विरासत में नहीं मिला है, हालाँकि, पुरानी शैली की कक्षाएं निश्चित रूप से, एक दूसरे से विरासत में मिली हैं। ऑब्जेक्ट से इनहेरिट करना इस बात की गारंटी देता है कि प्रत्येक पायथन वर्ग में कुछ कार्यक्षमता उपलब्ध है। पायथन 2.2 में नई शैली की कक्षाएं शुरू की गईं


8
रूट क्लास objectको कॉल करना सभी भ्रामक नहीं है, और वास्तव में यह बहुत मानक है। स्मॉलटाक में एक रूट क्लास है Object, और एक रूट मेटाक्लास नाम दिया गया है Class। क्यों? क्योंकि, जैसा Dogकि कुत्तों के लिए Objectएक वर्ग है, वस्तुओं के लिए एक वर्ग है, और Classकक्षाओं के लिए एक वर्ग है। जावा, C #, ObjC, रूबी, और अधिकांश अन्य वर्ग-आधारित OO भाषाएँ जो लोग आज उपयोग करते हैं जिनकी जड़ वर्ग है Object, केवल पायथन ही नहीं बल्कि नाम के रूप में भी कुछ भिन्नता का उपयोग करते हैं ।
अचानक

30

हां, यह ऐतिहासिक है । इसके बिना, यह एक पुरानी शैली की क्लास बनाता है।

यदि आप type()एक पुरानी शैली की वस्तु पर उपयोग करते हैं, तो आपको बस "उदाहरण" मिलता है। एक नई शैली की वस्तु पर आपको इसकी कक्षा मिलती है।


इसके अलावा, यदि आप type()पुरानी शैली की कक्षा में उपयोग करते हैं, तो आपको "टाइप" के बजाय "क्लासोबज" मिलता है।
जोएल सोजग्रेन

7

वर्ग निर्माण कथन का वाक्य विन्यास:

class <ClassName>(superclass):
    #code follows

किसी भी अन्य सुपरक्लेसेस की अनुपस्थिति में जिसे आप विशेष रूप से विरासत में लेना चाहते हैं, superclassहमेशा होना चाहिए object, जो कि पायथन में सभी वर्गों की जड़ है।

objectतकनीकी रूप से पायथन में "नई शैली" कक्षाओं की जड़ है। लेकिन आज नई शैली की कक्षाएं कक्षाओं की एकमात्र शैली के रूप में अच्छी हैं।

लेकिन, यदि आप objectकक्षाएं बनाते समय शब्द का स्पष्ट रूप से उपयोग नहीं करते हैं, तो जैसा कि दूसरों ने उल्लेख किया है, Python 3.x का स्पष्ट रूप से सुपरक्लास से विरासत में मिला है object। लेकिन मुझे लगता है कि स्पष्ट रूप से निहित (नरक) से हमेशा बेहतर है

संदर्भ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.