Was ist der Unterschied zwischen alten und neuen Stilklassen in Python? Wann sollte ich das eine oder andere verwenden?
Aus neuen und klassischen Klassen :
Bis zu Python 2.1 waren Klassen im alten Stil die einzige Variante, die dem Benutzer zur Verfügung stand.
Das Konzept der (alten) Klasse hat nichts mit dem Konzept des Typs zu tun: Wenn
x
es sich um eine Instanz einer alten Klasse handelt,x.__class__
bezeichnet es die Klasse vonx
, ist es abertype(x)
immer<type 'instance'>
.Dies spiegelt die Tatsache wider, dass alle Instanzen alten Stils unabhängig von ihrer Klasse mit einem einzigen integrierten Typ implementiert werden, der als Instanz bezeichnet wird.
In Python 2.2 wurden Klassen neuen Stils eingeführt, um die Konzepte von Klasse und Typ zu vereinheitlichen . Eine Klasse neuen Stils ist einfach ein benutzerdefinierter Typ, nicht mehr und nicht weniger.
Wenn x eine Instanz einer Klasse neuen Stils ist,
type(x)
ist dies normalerweise dasselbe wiex.__class__
(obwohl dies nicht garantiert ist - eine Klasseninstanz neuen Stils darf den zurückgegebenen Wert überschreibenx.__class__
).Die Hauptmotivation für die Einführung neuer Klassen besteht darin, ein einheitliches Objektmodell mit einem vollständigen Metamodell bereitzustellen .
Es hat auch eine Reihe von unmittelbaren Vorteilen, wie die Möglichkeit, die meisten integrierten Typen in Unterklassen zu unterteilen, oder die Einführung von "Deskriptoren", die berechnete Eigenschaften ermöglichen.
Aus Kompatibilitätsgründen sind Klassen standardmäßig immer noch im alten Stil .
Klassen neuen Stils werden erstellt, indem eine andere Klasse neuen Stils (dh ein Typ) als übergeordnete Klasse oder das Objekt "Typ der obersten Ebene" angegeben wird, wenn kein anderes übergeordnetes Objekt benötigt wird.
Das Verhalten von Klassen neuen Stils unterscheidet sich von dem von Klassen alten Stils in einer Reihe wichtiger Details, zusätzlich zu dem Typ, der zurückgegeben wird.
Einige dieser Änderungen sind für das neue Objektmodell von grundlegender Bedeutung, beispielsweise die Art und Weise, wie spezielle Methoden aufgerufen werden. Andere sind "Korrekturen", die aus Kompatibilitätsgründen zuvor nicht implementiert werden konnten, wie z. B. die Reihenfolge der Methodenauflösung bei Mehrfachvererbung.
Python 3 hat nur Klassen neuen Stils .
Unabhängig davon, ob Sie eine Unterklasse von haben
object
oder nicht, sind Klassen in Python 3 neu.
type(x)
. Wenn ich einen eingebauten Typ nicht unterklassifiziere, scheint es keinen Vorteil zu geben, den ich von den Klassen neuen Stils sehen kann. Es gibt einen Nachteil, nämlich die zusätzliche Eingabe von(object)
.super()
funktionieren nicht in Klassen alten Stils. Ganz zu schweigen davon, wie dieser Artikel sagt, dass es grundlegende Korrekturen wie MRO und spezielle Methoden gibt, was mehr als ein guter Grund ist, es zu verwenden.Deklarationstechnisch:
Klassen neuen Stils erben vom Objekt oder von einer anderen Klasse neuen Stils.
Old-Style-Klassen nicht.
Python 3 Hinweis:
Python 3 unterstützt keine Klassen im alten Stil, daher führt jede der oben genannten Formen zu einer Klasse im neuen Stil.
quelle
object
.class AnotherOldStyleClass: pass
class A: pass
undclass A(): pass
sind streng gleichwertig. Das erste bedeutet "A erbt keine übergeordnete Klasse" und das zweite bedeutet "A erbt keine übergeordnete Klasse" . Das ist ziemlich ähnlich zunot is
undis not
Wichtige Verhaltensänderungen zwischen alten und neuen Stilklassen
Exception
(Beispiel unten) abgeleitet wurden.__slots__
hinzugefügtMRO (Method Resolution Order) geändert
Es wurde in anderen Antworten erwähnt, aber hier ist ein konkretes Beispiel für den Unterschied zwischen klassischem MRO und C3-MRO (in neuen Stilklassen verwendet).
Die Frage ist die Reihenfolge, in der Attribute (einschließlich Methoden und Elementvariablen) in Mehrfachvererbung gesucht werden.
Klassische Klassen führen eine Tiefensuche von links nach rechts durch. Stoppen Sie beim ersten Spiel. Sie haben das
__mro__
Attribut nicht.Neue Klassen MRO ist komplizierter in einem einzigen englischen Satz zu synthetisieren. Es wird hier ausführlich erklärt . Eine seiner Eigenschaften ist, dass eine Basisklasse erst gesucht wird, wenn alle abgeleiteten Klassen vorhanden sind. Sie haben das
__mro__
Attribut, das die Suchreihenfolge anzeigt.Neue Stilklassenobjekte können nur ausgelöst werden, wenn sie von abgeleitet sind
Exception
Um Python 2.5 konnten viele Klassen erhöht werden, und um Python 2.6 wurde dies entfernt. Unter Python 2.7.3:
quelle
Alte Stilklassen sind für die Attributsuche immer noch geringfügig schneller. Dies ist normalerweise nicht wichtig, kann jedoch in leistungsempfindlichem Python 2.x-Code hilfreich sein:
quelle
%timeit aobj.a
10000000 loops, best of 3: 66.1 ns per loop
%timeit bobj.a
10000000 loops, best of 3: 53.9 ns per loop
Guido hat The Inside Story über Klassen im neuen Stil geschrieben , einen wirklich großartigen Artikel über Klassen im neuen und alten Stil in Python.
Python 3 hat nur eine neue Klasse. Selbst wenn Sie eine Klasse im alten Stil schreiben, wird sie implizit von abgeleitet
object
.Klassen im neuen Stil haben einige erweiterte Funktionen, die in Klassen im alten Stil fehlen, wie z. B.
super
das neue C3 mro , einige magische Methoden usw.quelle
Hier ist ein sehr praktischer, wahr / falsch Unterschied. Der einzige Unterschied zwischen den beiden Versionen des folgenden Codes besteht darin, dass in der zweiten Version Person vom Objekt erbt . Davon abgesehen sind die beiden Versionen identisch, jedoch mit unterschiedlichen Ergebnissen:
Klassen im alten Stil
Klassen neuen Stils
quelle
_names_cache
ist ein Wörterbuch, das jeden Namen, an den Sie übergeben, zwischenspeichert (zum späteren Abrufen speichert)Person.__new__
. Die setdefault-Methode (in einem beliebigen Wörterbuch definiert) verwendet zwei Argumente: einen Schlüssel und einen Wert. Befindet sich der Schlüssel im Diktat, wird sein Wert zurückgegeben. Wenn es nicht im Diktat enthalten ist, wird es zuerst auf den als zweites Argument übergebenen Wert gesetzt und dann zurückgegeben.__new__()
immer aufgerufen wird, und es konstruiert immer ein neues Objekt und wirft es dann. In diesem Fallif
ist a dem vorzuziehen.setdefault()
.__new__
ist eigentlich keine Sache für Klassen alten Stils, es wird nicht in der Instanzkonstruktion verwendet (es ist nur ein zufälliger Name, der besonders aussieht, wie das Definieren__spam__
). Das Konstruieren der Klasse im alten Stil ruft also nur auf__init__
, während die Konstruktion im neuen Stil__new__
(Zusammenführen zu einer Singleton-Instanz nach Namen) aufruft__init__
, um sie zu konstruieren und zu initialisieren.Klassen neuen Stils erben von
object
Python 2.2 und müssen als solche geschrieben werden (dhclass Classname(object):
anstelle vonclass Classname:
). Die wichtigste Änderung besteht darin, Typen und Klassen zu vereinheitlichen. Der nette Nebeneffekt besteht darin, dass Sie von integrierten Typen erben können.Lesen Sie die Beschreibung für weitere Details.
quelle
Neue Stilklassen können verwenden,
super(Foo, self)
woFoo
eine Klasse undself
die Instanz ist.Und in Python 3.x können Sie einfach
super()
innerhalb einer Klasse ohne Parameter verwenden.quelle