super () hatayla başarısız oluyor: Üst nesne nesneden devralmadığında TypeError “argüman 1 classobj değil tür olmalıdır”


197

Anlayamadığım bir hata alıyorum. Herhangi bir ipucu benim örnek kod ile sorun nedir?

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

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

print C().meth(1)

'Süper' yerleşik yöntem yardımıyla örnek test kodunu aldım.

İşte hata:

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, işte python'un kendisinden yardım (süper):

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 ?? Bu bir programlama terimi mi, yoksa biliyor musunuz? Lütfen açıkla.
Cplusplusplus

3
@Cplusplusplus: muhtemelen Yöntem ;-) anlamına gelir
ShadowFlame

Yanıtlar:


335

Sorununuz, B sınıfının "yeni stil" sınıfı olarak bildirilmemesidir. Bunu şu şekilde değiştirin:

class B(object):

ve işe yarayacak.

super()ve tüm alt sınıf / üst sınıf şeyler yalnızca yeni stil sınıflarıyla çalışır. Yeni (object)bir sınıf olduğundan emin olmak için her zaman herhangi bir sınıf tanımına yazmayı alışkanlık haline getirmenizi tavsiye ederim .

Eski tarz sınıflar ("klasik" sınıflar olarak da bilinir) her zaman türdendir classobj; yeni stil sınıfları türdendir type. Bu yüzden gördüğünüz hata mesajını aldınız:

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

Kendiniz görmek için bunu deneyin:

class OldStyle:
    pass

class NewStyle(object):
    pass

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

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

Python 3.x'te tüm sınıfların yeni stil olduğunu unutmayın. Yine de eski stil sınıflarından sözdizimini kullanabilirsiniz, ancak yeni stil sınıfına sahip olursunuz. Yani, Python 3.x'te bu sorunla karşılaşmayacaksınız.


ilginç, benzer bir hata (TypeError: tip olmalı, classobj değil) fırlatıp Py33 üzerinde çalışan bottle.py ( bottlepy.org ) çalıştıran bu sorunu buldum.
bootload

Python 3.x'te artık "eski stil" sınıfları yoktur. "Eski stil" bildirimini kullanan kod yine de "yeni stil" sınıfını bildirir, bu nedenle Python 3.x'te bu hata oluşmaz.
steveha

1
Düzenlemek için B sınıfı mevcut değilse, kullanmaya çalışmamak için A sınıfını düzenlemeniz gerekir super(); A sınıfı bir "eski tarz" sınıfla çalışmak için yapılmalıdır ve muhtemelen bunu yapmanın en iyi yolu, A sınıfının kendisini "eski tarz" bir sınıf haline getirmektir. Elbette tüm programınızı Python 3.x'de çalışacak şekilde yükseltmenizi öneririm, böylece ne yaparsanız yapın tüm sınıflar yeni stil olacak; bu seçenek varsa en iyi seçenektir.
steveha

Aynı sorun var, ama benim temel sınıf gibi ilan edildi class B(object):. Bu hatayı @mock.patch('module.B', autospec=B)test durumumdan hemen önce kullandığım için alıyorum . Bunu nasıl düzeltebileceğine dair düşüncelerin var mı?
MikeyE

155

Ayrıca, B sınıfını değiştiremiyorsanız, birden çok kalıtım kullanarak hatayı düzeltebilirsiniz.

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
Yorum bırakmak için yardımcı olamadım, bu 'standart' cevap olarak kabul edilmelidir.
workplaylifecycle

9
Gelecekte Google çalışanları Python 2.6'ya yapıştı: Bu muhtemelen istediğiniz cevap! Temel sınıfı değiştiremediğinizde (örneğin, standart bir kitaplık sınıfını alt sınıflandırıyorsanız), kendi sınıfınızdaki bu değişiklik super () öğesini düzeltir.
coredumperror

Bana iyi geldi, Birisi nasıl çalıştığını açıklayabilir misin?
subro

@subro, bu da sınıfınızı bir "yeni stil" sınıfı yapar (burada sınıf nesnesi tiptedir type) ve yine de "eski stil" sınıfını (sınıf nesnesi tür olan classobj) alt sınıfa ayırır . super()yeni stil sınıflarıyla çalışır, ancak eski stil sınıflarıyla çalışmaz.
MarSoft

mükemmel cevap!
Tom

18

Python sürümü 3.X ise, sorun değil.

Bence python sürüm 2.X, süper bu kodu eklerken işe yarayacak

__metaclass__ = type

yani kod

__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 kullandığımda da yayınlanan sorunla karşı karşıya kaldım. Python 3.4 ile çok iyi çalışıyor

Python 2.7'de çalışması için bu __metaclass__ = typeözelliği programımın en üstüne ekledim ve işe yaradı.

__metaclass__ : Eski tarz sınıflardan ve yeni tarz sınıflardan geçişi kolaylaştırır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.