Python super () löst TypeError aus

109

In Python 2.5 löst der folgende Code ein TypeError:

>>> class X:
      def a(self):
        print "a"

>>> class Y(X):
      def a(self):
        super(Y,self).a()
        print "b"

>>> c = Y()
>>> c.a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in a
TypeError: super() argument 1 must be type, not classobj

Wenn ich die ersetzen class Xmit class X(object), wird es funktionieren. Was ist die Erklärung dafür?

Geo
quelle
3
Ihr "aber ich ersetze Klasse X durch Klasse X (Objekt)" hat mein Problem behoben! Danke
AliBZ

Antworten:

132

Der Grund dafür ist, dass super()nur Klassen neuen Stils verwendet werden , was in der 2.x-Serie bedeutet, dass Folgendes erweitert wird object:

>>> class X(object):
        def a(self):
            print 'a'

>>> class Y(X):
        def a(self):
            super(Y, self).a()
            print 'b'

>>> c = Y()
>>> c.a()
a
b
Cody Brocious
quelle
4
Ab welcher Python-Version wurde dies zum Standardverhalten?
Geo
6
In 2.2 wurden Klassen neuen Stils eingeführt, in 3.0 wurden sie zum Standard.
Cody Brocious
7
@tsunami Wenn du in die Superklasse kommen willst, mach "Xa (Selbst)"
James Brady
Ich denke du hast mich falsch verstanden . Triptychon. Ich erinnere mich, dass ich eine Python-Version unter 3.0 verwendet habe, und ich habe nicht ausdrücklich gesagt, dass meine Klasse von Object erbt, und der Aufruf von super hat funktioniert. Vielleicht ist es das Standardverhalten von 2.6? Nur sagen :)
Geo
Alabaster, das ist wirklich nicht nötig. Klassen im neuen Stil haben eine Vielzahl von Vorteilen, nicht nur super. Alte Wege sollten nicht gefördert werden.
Cody Brocious
14

Verwenden Sie außerdem nicht super (), es sei denn, Sie müssen. Es ist nicht das allgemeine "Richtige", mit Klassen neuen Stils zu tun, die Sie vielleicht vermuten.

Es gibt Zeiten, in denen Sie eine Mehrfachvererbung erwarten und möglicherweise möchten, aber bis Sie die haarigen Details des MRO kennen, lassen Sie es am besten in Ruhe und bleiben Sie bei:

 X.a(self)
Bobince
quelle
2
Ist das richtig, weil ich in meinen 6 Monaten Python / Django Super als "allgemeines richtiges Ding" verwendet habe?
Philgo20
1
Nun, es tut dir nicht weh für eine einzelne Vererbung an sich (außer dass es etwas langsamer ist), aber es bringt dir auch nichts für sich. Sie müssen alle Methoden entwerfen, die mehrfach vererbt werden müssen (insbesondere __init__), um Argumente auf saubere und vernünftige Weise zu durchlaufen. Andernfalls treten TypeErrors oder schlechtere Debugging-Probleme auf, wenn jemand versucht, mit Ihrer Klasse zu vererben. Wenn Sie nicht wirklich darauf ausgelegt sind, MI auf diese Weise zu unterstützen (was ziemlich schwierig ist), ist es wahrscheinlich besser zu vermeiden, superdass die Methode MI-sicher ist.
Bobince
3

Falls keine der oben genannten Antworten dies klar erwähnte. Ihre übergeordnete Klasse muss von "Objekt" erben, wodurch es im Wesentlichen zu einer neuen Stilklasse wird.

# python 3.x:
class ClassName(object): # This is a new style class
    pass

class ClassName: # This is also a new style class ( implicit inheritance from object )
    pass

# Python 2.x:
class ClassName(object): # This is a new style class
    pass

class ClassName:         # This is a old style class
    pass
Abhi Tk
quelle
Entschuldigung, aber in Python 3.x funktioniert Ihr zweites Beispiel (implizite Vererbung) im Kontext des genannten Problems nicht wirklich.
Sophros
1

Ich habe die verschiedenen Xa () -Methoden ausprobiert. Sie scheinen jedoch eine Instanz von X zu benötigen, um a () auszuführen, also habe ich X (). a (self) ausgeführt, was zumindest für die Anwendungen, auf die ich gestoßen bin, vollständiger zu sein scheint als die vorherigen Antworten. Es scheint keine gute Möglichkeit zu sein, das Problem zu lösen, da unnötige Konstruktionen und Zerstörungen erforderlich sind, aber es funktioniert einwandfrei.

Meine spezielle Anwendung war das cmd.Cmd-Modul von Python, das aus irgendeinem Grund offensichtlich kein NewStyle-Objekt ist.

Endergebnis:

X().a(self)
weberc2
quelle