Sollten alle Python-Klassen das Objekt erweitern?

129

Ich habe festgestellt, dass beide der folgenden Arbeit:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

Sollten alle Python-Klassen das Objekt erweitern? Gibt es mögliche Probleme, wenn das Objekt nicht erweitert wird?

Kara
quelle
2
Gibt es einen Unterschied zwischen class Foo():und class Foo:? Wie ich beobachte, arbeiten beide in Python 3.
Wolf
Es ist gut beantwortet in dieser Frage: stackoverflow.com/questions/4015417/…
nngeek

Antworten:

117

Wenn Sie in Python 2 nicht von erben, objectwird eine Klasse im alten Stil erstellt, die unter anderem typezu unterschiedlichen Ergebnissen führt:

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

vs.

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

Auch die Regeln für die Mehrfachvererbung unterscheiden sich in einer Weise, die ich hier nicht einmal zusammenfassen möchte. Alle guten Dokumentationen, die ich über MI gesehen habe, beschreiben Klassen neuen Stils.

Schließlich sind Klassen alten Stils in Python 3 verschwunden, und die Vererbung von objectist implizit geworden. Bevorzugen Sie daher immer neue Stilklassen, es sei denn, Sie benötigen Abwärtskompatibilität mit alter Software.

Fred Foo
quelle
68

In Python 3 werden Klassen objectimplizit erweitert, unabhängig davon, ob Sie dies selbst sagen oder nicht.

In Python 2 gibt es Klassen im alten und neuen Stil . Um zu signalisieren, dass eine Klasse einen neuen Stil hat, müssen Sie explizit von erben object. Wenn nicht, wird die Implementierung im alten Stil verwendet.

Sie möchten im Allgemeinen eine Klasse neuen Stils. Von objectexplizit erben . Beachten Sie, dass dies auch für Python 3-Code gilt, der mit Python 2 kompatibel sein soll.

Slezica
quelle
Ja, der Unterschied, auf den Free Foo hingewiesen hat , ist verschwunden. Übrigens: Sind die leeren Klammern optional?
Wolf
4
Es gibt viel Python 3-Code, der foo (Objekt) verwendet:. Ist das dann nur eine Konvention?
RFV5s
2
@RFVenter Es kann sich um Code handeln, der sowohl unter Python 2 als auch unter Python 3 ausgeführt werden soll. In diesem Fall müssen Sie das Objekt explizit unterklassifizieren, damit sich die Klasse unter Python 2 weitgehend gleich verhält.
blubberdiblub
@blubberdiblub Das habe ich vermutet, ABER unser Projekt läuft ausschließlich auf Python 3.5 Virtualenv. Ich denke, der Code muss aus einem Python 2-Projekt kopiert worden sein.
RFV5s
@ RFVenter yup, das kann eine andere Erklärung sein. Und wenn es erst jetzt Python 3.x ist, ist es natürlich in Ordnung, die Objektreferenzen zu entfernen.
Blubberdiblub
17

In Python 3 können Sie eine Klasse auf drei verschiedene Arten erstellen und intern sind alle gleich (siehe Beispiele). Es spielt keine Rolle, wie Sie eine Klasse erstellen, alle Klassen in Python 3 erben von einer speziellen Klasse namens object . Das Klassenobjekt ist von grundlegender Bedeutung Klasse in Python und bietet viele Funktionen wie Doppelstrich Methoden, Deskriptoren, super () Methode, eine Eigenschaft () Methode usw.

Beispiel 1.

class MyClass:
 pass

Beispiel 2.

class MyClass():
 pass

Beispiel 3.

class MyClass(object):
  pass
N Randhawa
quelle
1
Dies ist nicht unbedingt wahr ... stackoverflow.com/questions/1238606/…
Philip Adler
Ich bin mir nicht sicher, ob ich dir folge. Und ja, wahrscheinlich für die meisten Menschen nicht relevant, bis es relevant ist.
Philip Adler
@PhilipAdler Es wird allgemein angenommen, dass objectauf eingebaute Bezug genommen wird object. Wenn wir berücksichtigen müssen, dass die in CPython integrierte Kennung ersetzt werden kann, können wir kaum Aussagen über das Datenmodell machen. Kann man ernsthaft argumentieren, dass streine Zeichenfolge nicht immer als Argument akzeptiert wird, weil man sie zuweisen könnte builtins.str = None?
Nuno André
Ich sehe immer wieder die Behauptung, dass dies "weit verbreitet" ist, und ich akzeptiere, dass es eine Annahme ist, die jede aktuelle Implementierung macht (es ist keine Anforderung der Sprache), es war nicht meine Erfahrung, dass die Mehrheit der Python-Programmierer ich Ich habe mich getroffen, nehme dies an, weiß davon oder habe es sogar in Betracht gezogen. Unabhängig davon macht die Behauptung, dass allgemein angenommen wird, auch wenn sie wahr ist, meine Behauptung, dass die Äquivalenz nicht streng wahr ist, nicht ungültig .
Philip Adler
1

Ja, alle Python-Klassen sollten das Objekt erweitern (oder besser gesagt Unterklasse, hier ist Python). Während normalerweise keine ernsthaften Probleme auftreten, ist dies in einigen Fällen (wie bei mehreren Vererbungsbäumen) wichtig. Dies gewährleistet auch eine bessere Kompatibilität mit Python 3.

Pydsigner
quelle
1
Genau genommen, wenn Sie dies nicht tun, erhalten Sie eine klassische Klasse, aber dies hat keine wirklichen Vorteile und wird von Python 3 sowieso nicht unterstützt
max k.
Ich bin gespannt, warum es die Kompatibilität mit Python3 verbessert. Nach meinem Verständnis wird Python3 das Objekt automatisch erweitern, auch wenn Sie es nicht angeben, oder?
Paul Lo
2
@PaulLo Richtig, aber wenn Sie explizit vom Objekt erben, erhalten Sie sowohl in Python 2 als auch in Python 3 das gleiche Verhalten (im neuen Stil). Es geht nicht darum, die Funktionsweise von Python 3 zu ändern, sondern darum, Forward zu verwenden -Kompatibilität auf Python 2.
Pydsigner
Dieser Vorschlag sieht nicht sehr elegant aus, aber falls Sie Python2 und Python3 ansprechen, scheint er effektiv zu sein. Aber wie relevant ist es in der Praxis?
Wolf
@ Wolf Es kommt darauf an, was du tust. Wenn Sie komplexe Vererbungsbäume haben, ist dies sehr wichtig. Wenn Ihre Klasse ein Deskriptor sein soll, müssen Sie den neuen Stil verwenden. Sie können den Links von stackoverflow.com/questions/54867/… folgen, wenn Sie detailliertere Informationen wünschen.
Pydsigner
1

In Python3 gibt es keinen Unterschied, aber in Python2, wenn Sie nicht erweitern, erhalten objectSie Klassen im alten Stil. Sie möchten eine Klasse im neuen Stil gegenüber einer Klasse im alten Stil verwenden.

thkang
quelle
1
Diese Antwort ist vernünftig, aber andere Antwortende kamen schneller und / oder detaillierter an. Diese Antwort fügt der Seite in ihrer jetzigen Form keinen Wert hinzu.
Mark Amery
1

Wie bereits in anderen Antworten erwähnt, ist die Python 3-Vererbung vom Objekt implizit. Aber sie geben nicht an, was Sie tun sollen und was Konvention ist.

Die Dokumentationsbeispiele für Python 3 verwenden alle den folgenden Stil, der Konvention ist. Ich empfehle daher, diesen für jeden zukünftigen Code in Python 3 zu befolgen.

class Foo:
    pass

Quelle: https://docs.python.org/3/tutorial/classes.html#class-objects

Beispielzitat:

Klassenobjekte unterstützen zwei Arten von Operationen: Attributreferenzen und Instanziierung.

Attributreferenzen verwenden die Standardsyntax, die für alle Attributreferenzen in Python verwendet wird: obj.name. Gültige Attributnamen sind alle Namen, die sich beim Erstellen des Klassenobjekts im Namespace der Klasse befanden. Wenn also die Klassendefinition so aussah:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

Ein weiteres Zitat:

Im Allgemeinen beziehen sich Instanzvariablen auf Daten, die für jede Instanz eindeutig sind, und Klassenvariablen auf Attribute und Methoden, die von allen Instanzen der Klasse gemeinsam genutzt werden:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance
jmoz
quelle