super () kończy się niepowodzeniem z błędem: TypeError „argument 1 musi być typem, a nie classobj”, gdy rodzic nie dziedziczy po obiekcie


196

Mam błąd, którego nie mogę zrozumieć. Masz jakieś pojęcie, co jest nie tak z moim przykładowym kodem?

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

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

print C().meth(1)

Otrzymałem przykładowy kod testowy z pomocą wbudowanej metody „super”.

Oto błąd:

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

Do Twojej wiadomości, oto pomoc (super) samego Pythona:

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 Czy to termin programowania, czy ... wiesz? Proszę o wyjaśnienie.
— Cplusplusplus

3
@Cplusplusplus: prawdopodobnie oznacza Metodę ;-)
— ShadowFlame

Odpowiedzi:


333

Problem polega na tym, że klasa B nie została zadeklarowana jako klasa „nowego stylu”. Zmień to tak:

class B(object):

i zadziała.

super()i wszystkie elementy podklasy / superklasy działają tylko z klasami w nowym stylu. Zalecam, abyś przyzwyczaił się zawsze wpisywać to (object)w dowolnej definicji klasy, aby mieć pewność, że jest to klasa nowego stylu.

Klasy w starym stylu (znane również jako klasy „klasyczne”) są zawsze typu classobj; klasy w nowym stylu są typu type. Oto dlaczego zobaczyłeś komunikat o błędzie:

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

Spróbuj tego, aby przekonać się sam:

class OldStyle:
    pass

class NewStyle(object):
    pass

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

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

Zauważ, że w Pythonie 3.x wszystkie klasy są w nowym stylu. Nadal możesz używać składni z klas starego stylu, ale otrzymujesz klasę nowego stylu. Tak więc w Pythonie 3.x nie będziesz mieć tego problemu.


interesujące, znalazłem ten właśnie problem z uruchomieniem bottle.py ( bottlepy.org ), który generuje podobny błąd (TypeError: must be type, not classobj) działający na Py27, ale nie Py33.
— bootload

W Pythonie 3.x nie ma już klas „w starym stylu”. Kod korzystający z deklaracji „starego stylu” nadal deklaruje klasę „nowego stylu”, więc ten błąd nie może wystąpić w Pythonie 3.x.
— steveha

1
Jeśli klasa B nie jest dostępna do edycji, musisz edytować klasę A, aby nie próbować jej używać super(); klasa A musi być przystosowana do pracy z klasą „w starym stylu”, a być może najlepszym sposobem na to byłoby uczynienie klasy A samą klasą „w starym stylu”. Oczywiście polecam uaktualnienie całego programu do działania w Pythonie 3.x, aby wszystkie klasy miały nowy styl bez względu na to, co robisz; jeśli ta opcja jest dostępna, jest to najlepsza opcja.
— steveha,

Mam ten sam problem, ale moja podstawowa klasa jest zadeklarowana jako class B(object):. Otrzymuję ten błąd z powodu użycia @mock.patch('module.B', autospec=B)tuż przed moim przypadkiem testowym. Wszelkie przemyślenia, jak to naprawić?
— MikeyE,

154

Ponadto, jeśli nie możesz zmienić klasy B, możesz naprawić błąd, używając wielokrotnego dziedziczenia.

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
Nie mogłem pomóc w pozostawieniu komentarza, ten należy zaakceptować jako „standardową” odpowiedź.
— cykl roboczy,

9
Dla przyszłych pracowników Google, którzy utknęli w Pythonie 2.6: jest to odpowiedź, której prawdopodobnie chcesz! Kiedy nie możesz zmienić klasy podstawowej (np. Podklasujesz klasę biblioteki standardowej), ta zmiana na własną klasę naprawia super ().
— coredumperror

Działa mi to dobrze. Czy ktoś może wyjaśnić, jak to działa?
— subro

@ subro, to sprawia, że ​​twoja klasa jest klasą „nowego stylu” (gdzie obiekt klasy jest typu type), a jednocześnie podklasuje klasę „starego stylu” (której obiekt klasy jest typu classobj). super()działa z klasami w nowym stylu, ale nie z klasami w starym stylu.
— MarSoft,

idealna odpowiedź!
— Tom

18

Jeśli wersja Pythona to 3.X, jest w porządku.

Myślę, że twoja wersja Pythona to 2.X, super działałoby podczas dodawania tego kodu

__metaclass__ = type

więc kod jest

__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

Wystąpił również problem z opublikowanym problemem, gdy korzystałem z Pythona 2.7. Działa bardzo dobrze z Pythonem 3.4

Aby działał w Pythonie 2.7, dodałem __metaclass__ = typeatrybut u góry mojego programu i działał.

__metaclass__ : Ułatwia przejście z klas w starym stylu do klas w nowym stylu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.