सुपर () त्रुटि के साथ विफल रहता है: टाइपऑयॉर "तर्क 1 टाइप होना चाहिए, न कि क्लासोबज" जब माता-पिता को ऑब्जेक्ट से विरासत में नहीं मिलता है


196

मुझे कुछ त्रुटि मिलती है जिसे मैं समझ नहीं सकता। कोई भी नमूना जो मेरे नमूना कोड में गलत है?

class B:
    def meth(self, arg):
        print arg

class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

मुझे 'सुपर' बिल्ट-इन पद्धति की मदद से नमूना परीक्षण कोड मिला।

यहाँ त्रुटि है:

Traceback (most recent call last):
  File "./test.py", line 10, in ?
    print C().meth(1)
  File "./test.py", line 8, in meth
    super(C, self).meth(arg)
TypeError: super() argument 1 must be type, not classobj

FYI, यहाँ अजगर से ही मदद (सुपर) है:

Help on class super in module __builtin__:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super(C, self).meth(arg)
 |


3
Meth ?? क्या यह एक प्रोग्रामिंग शब्द है, या ... y'know? कृपया स्पष्ट करें।
Cplusplusplus

3
@ अधिशेष: शायद विधि के लिए खड़ा है ;-)
ShadowFlame

जवाबों:


333

आपकी समस्या यह है कि वर्ग बी को "नई शैली" वर्ग के रूप में घोषित नहीं किया गया है। इसे ऐसे बदलें:

class B(object):

और यह काम करेगा।

super()और सभी उपवर्ग / सुपरक्लास सामान केवल नई शैली की कक्षाओं के साथ काम करते हैं। मैं आपको हमेशा टाइप करने की आदत में शामिल होने की सलाह देता हूं कि (object)किसी भी वर्ग परिभाषा पर यह सुनिश्चित करने के लिए कि यह एक नई शैली की कक्षा है।

पुरानी शैली की कक्षाएं (जिन्हें "क्लासिक" कक्षाएं भी कहा जाता है) हमेशा प्रकार की होती हैं classobj; नई शैली के वर्ग प्रकार के होते हैं type। यही कारण है कि आपको त्रुटि संदेश मिला जिसे आपने देखा:

TypeError: super() argument 1 must be type, not classobj

इसे अपने लिए देखने का प्रयास करें:

class OldStyle:
    pass

class NewStyle(object):
    pass

print type(OldStyle)  # prints: <type 'classobj'>

print type(NewStyle) # prints <type 'type'>

ध्यान दें कि पायथन 3.x में, सभी वर्ग नई शैली के हैं। आप अभी भी पुरानी शैली की कक्षाओं से वाक्य रचना का उपयोग कर सकते हैं लेकिन आपको एक नई शैली की कक्षा मिलती है। तो, पायथन 3.x में आपको यह समस्या नहीं होगी।


दिलचस्प है, मुझे यह सटीक समस्या चल रही है बॉटमहोम ( बॉटलफ़ी डॉट ओआरजी ) जो एक समान त्रुटि फेंकता है ( टाइपऑयॉर : टाइप होना चाहिए, न कि क्लासबॉज) प्यू 27 पर चल रहा है, लेकिन प्यू 33 नहीं।
बूटलोड

पायथन 3.x में, "पुरानी-शैली" वर्ग नहीं हैं। "पुरानी शैली" घोषणा का उपयोग करते हुए कोड अभी भी एक "नई शैली" वर्ग की घोषणा करता है, इसलिए यह त्रुटि पायथन 3.11 में नहीं हो सकती है।
स्टेवेहा

1
यदि क्लास बी आपको संपादित करने के लिए उपलब्ध नहीं है, तो आपको उपयोग करने की कोशिश न करने के लिए कक्षा ए को संपादित करना होगा super(); क्लास ए को "पुरानी शैली" वाली क्लास के साथ काम करने के लिए बनाया जाना चाहिए, और संभवतः ऐसा करने का सबसे अच्छा तरीका क्लास ए खुद एक "पुरानी शैली" वाली क्लास होगी। बेशक, मैं आपके पूरे कार्यक्रम को केवल पायथन 3.x में चलाने के लिए अपग्रेड करने की सलाह देता हूं, ताकि सभी वर्ग नई शैली के हों, चाहे आप कुछ भी करें; अगर वह विकल्प उपलब्ध है तो यह सबसे अच्छा विकल्प है।
स्टीवेहा

मेरे पास एक ही मुद्दा है, लेकिन मेरे आधार वर्ग को घोषित किया गया है class B(object):। मुझे यह त्रुटि @mock.patch('module.B', autospec=B)मेरे परीक्षण मामले से पहले उपयोग करने के कारण मिल रही है । इसे ठीक करने के बारे में कोई विचार?
मिकी

154

साथ ही, यदि आप कक्षा B को नहीं बदल सकते हैं, तो आप एकाधिक वंशानुक्रम का उपयोग करके त्रुटि को ठीक कर सकते हैं।

class B:
    def meth(self, arg):
        print arg

class C(B, object):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

16
मैं एक टिप्पणी छोड़ने में मदद नहीं कर सकता, यह 'मानक' उत्तर के रूप में स्वीकार किया जाना चाहिए।
workplaylifecycle

9
भविष्य के गुगलों के लिए अजगर 2.6 पर अटक गया: यह वह उत्तर है जो आप शायद चाहते हैं! जब आप बेस क्लास को नहीं बदल सकते (जैसे आप एक मानक लाइब्रेरी क्लास को उपवर्गित कर रहे हैं), तो यह परिवर्तन आपकी अपनी कक्षा के सुपर () को ठीक करता है।
coredumperror

यह मेरे लिए ठीक है, क्या आप किसी को समझा सकते हैं कि यह कैसे काम करता है?
सुब्रो

@subro, यह आपकी कक्षा को एक "नई-शैली" वर्ग बनाता है (जहाँ कक्षा वस्तु प्रकार की होती है type) जबकि "पुरानी-शैली" वर्ग (जिसका वर्ग वस्तु प्रकार का होता है ) को उपवर्गित करते हुए classobjsuper()नई शैली की कक्षाओं के साथ काम करता है लेकिन पुरानी शैली की कक्षाओं के साथ नहीं।
MarSoft

सही जवाब!
टॉम

18

अगर अजगर संस्करण 3.X है, तो यह ठीक है।

मुझे लगता है कि आपका अजगर संस्करण 2.X है, इस कोड को जोड़ने पर सुपर काम करेगा

__metaclass__ = type

तो कोड है

__metaclass__ = type
class B:
    def meth(self, arg):
        print arg
class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)
print C().meth(1)

4

जब मुझे python 2.7 का उपयोग किया गया था तो मुझे पोस्ट किए गए मुद्दे का सामना करना पड़ा था। यह अजगर 3.4 के साथ बहुत अच्छा काम कर रहा है

अजगर 2.7 में इसे काम करने के लिए मैंने __metaclass__ = typeअपने कार्यक्रम के शीर्ष पर विशेषता जोड़ी है और यह काम किया है।

__metaclass__ : यह पुरानी शैली की कक्षाओं और नई शैली की कक्षाओं से संक्रमण को कम करता है।

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