Frage Was ist der Unterschied zwischen alten Stil und neuen Stilklassen in Python?


Was ist der Unterschied zwischen alten Stil und neuen Stilklassen in Python? Gibt es jemals einen Grund, die alten Klassen zu benutzen?


855
2017-09-10 18:01


Ursprung


Antworten:


Von http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes :

Bis Python 2.1 waren Old-Style-Klassen die einzigen, die dem Benutzer zur Verfügung standen. Das Konzept der (alten) Klasse steht in keinem Zusammenhang mit dem Konzept des Typs: if x ist dann eine Instanz einer Klasse im alten Stil x.__class__ bezeichnet die Klasse von x, aber type(x) ist immer <type 'instance'>. Dies spiegelt die Tatsache wider, dass alle Instanzen im alten Stil unabhängig von ihrer Klasse mit einem einzigen integrierten Typ, der sogenannten Instanz, implementiert werden.

In Python 2.2 wurden neue Stilklassen eingeführt, um die Konzepte von Klasse und Typ zu vereinheitlichen. Eine neue Stilklasse ist einfach ein benutzerdefinierter Typ, nicht mehr und nicht weniger. Wenn x eine Instanz einer neuen Stilklasse ist, dann type(x) ist in der Regel das Gleiche wie x.__class__ (Obwohl dies nicht garantiert ist, darf eine Klasseninstanz des neuen Stils den zurückgegebenen Wert überschreiben.) x.__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 Fähigkeit, die meisten eingebauten Typen abzuleiten, oder die Einführung von "Deskriptoren", die berechnete Eigenschaften ermöglichen.

Aus Kompatibilitätsgründen sind Klassen standardmäßig noch im alten Stil. Klassen im neuen Stil werden erstellt, indem eine andere Klasse im neuen Stil (d. H. Ein Typ) als übergeordnete Klasse oder das Objekt vom Typ "oberster Ebene" angegeben wird, wenn kein anderes übergeordnetes Element benötigt wird. Das Verhalten von New-Style-Klassen unterscheidet sich von dem von Old-Style-Klassen in einigen wichtigen Details zusätzlich zu dem Typ, der zurückgegeben wird. Einige dieser Änderungen sind grundlegend für das neue Objektmodell, so wie die Art, wie spezielle Methoden aufgerufen werden. Andere sind "Fixes", die zuvor aus Gründen der Kompatibilität nicht implementiert werden konnten, wie die Reihenfolge der Methodenauflösung bei Mehrfachvererbung.

Python 3 hat nur neue Stilklassen. Egal, ob Sie von object oder nicht, Klassen sind neu in Python 3.


487
2017-07-30 01:21



Erklärungweise:

New-Style-Klassen erben von Objekt oder von einer anderen New-Style-Klasse.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

Old-Style-Klassen nicht.

class OldStyleClass():
    pass

282
2017-11-13 09:36



Wichtiges Verhalten ändert sich zwischen alten und neuen Stilklassen

  • Super hinzugefügt
  • MRO geändert (erklärt unten)
  • Deskriptoren hinzugefügt
  • Neue Stilklassenobjekte können nicht erhöht werden, wenn sie nicht von abgeleitet werden Exception (Beispiel unten)
  • __slots__ hinzugefügt

MRO (Method Resolution Order) geändert

Es wurde in anderen Antworten erwähnt, aber hier geht ein konkretes Beispiel für den Unterschied zwischen klassischem MRO und C3 MRO (verwendet in neuen Stilklassen).

Die Frage ist die Reihenfolge, in der Attribute (einschließlich Methoden und Mitgliedsvariablen) in Mehrfachvererbung gesucht werden.

Klassische KlassenMachen Sie eine Tiefensuche von links nach rechts. Stoppen Sie beim ersten Spiel. Sie haben nicht die __mro__ Attribut.

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

Neue Stilklassen MRO ist komplizierter in einem einzigen englischen Satz zu synthetisieren. Es wird ausführlich erklärt Hier. Eine seiner Eigenschaften ist, dass nach einer Base-Klasse nur gesucht wird, wenn alle abgeleiteten Klassen vorhanden sind. Sie haben das __mro__ Attribut, das die Suchreihenfolge anzeigt.

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

Neue Stilklassenobjekte können nicht ausgelöst werden, wenn sie nicht von abgeleitet werden Exception

Um Python 2.5 herum konnten viele Klassen angesprochen werden, um Python 2.6 wurde das entfernt. Auf Python 2.7.3:

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False

195
2017-07-12 11:26



Alte Stilklassen sind bei der Attributsuche immer noch geringfügig schneller. Dies ist normalerweise nicht wichtig, kann aber im leistungssensitiven Python 2.x-Code nützlich sein:

In [3]: Klasse A:
   ...: def __init __ (selbst):
   ...: self.a = 'hallo da'
   ...:

In [4]: ​​Klasse B (Objekt):
   ...: def __init __ (selbst):
   ...: self.a = 'hallo da'
   ...:

In [6]: aobj = A ()
In [7]: bobj = B ()

In [8]:% zeitlicher aobj.a
10000000 Schleifen, beste von 3: 78,7 ns pro Schleife

In [10]:% zeitit bobj.a
10000000 Schleifen, bestes von 3: 86,9 ns pro Schleife

34
2018-04-24 13:41



Guido hat geschrieben Die Inside-Story in New-Style-Klassen, ein wirklich toller Artikel über Python in der neuen und alten Klasse.

Python 3 hat nur eine neue Stilklasse, selbst wenn Sie eine "Klasse im alten Stil" schreiben, wird sie implizit abgeleitet object.

New-Style-Klassen haben einige erweiterte Funktionen, die im alten Stil Klassen wie fehlen super und das Neue C3 MRO, einige magische Methoden, etc.


30
2017-10-09 13:40



Hier ist ein sehr praktischer, wahrer / falscher Unterschied. Der einzige Unterschied zwischen den zwei Versionen des folgenden Codes besteht darin, dass Person in der zweiten Version von Objekt erbt. Ansonsten sind die beiden Versionen identisch, aber mit unterschiedlichen Ergebnissen:

1) Klassen im alten Stil

class Person():
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed1 is ahmed2
print ahmed1
print ahmed2


>>> False
<__main__.Person instance at 0xb74acf8c>
<__main__.Person instance at 0xb74ac6cc>
>>>

2) neue Klassen

class Person(object):
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed2 is ahmed1
print ahmed1
print ahmed2

>>> True
<__main__.Person object at 0xb74ac66c>
<__main__.Person object at 0xb74ac66c>
>>>

17
2017-10-28 09:54



New-Style-Klassen erben von object und muss als solche in Python 2.2 geschrieben werden (d. h. class Classname(object): Anstatt von class Classname:). Die Kernveränderung besteht darin, Typen und Klassen zu vereinheitlichen, und der nette Nebeneffekt besteht darin, dass Sie von eingebauten Typen erben können.

Lesen beschreibend für mehr Details.


7
2018-04-30 08:28



Neue Stilklassen können verwenden super(Foo, self) woher Foo ist eine Klasse und self ist die Instanz.

super(type[, object-or-type])

Gibt ein Proxyobjekt zurück, das Methodenaufrufe an eine übergeordnete oder untergeordnete Klasse des Typs delegiert. Dies ist nützlich für den Zugriff auf vererbte Methoden, die in einer Klasse überschrieben wurden. Die Suchreihenfolge ist dieselbe wie die von getattr () verwendete, außer dass der Typ selbst übersprungen wird.

Und in Python 3.x kannst du es einfach verwenden super() innerhalb einer Klasse ohne Parameter.


4
2017-09-10 21:23



Oder Sie sollten immer neue Klassen verwenden, es sei denn Sie haben Code, der mit Versionen von Python älter als 2.2 arbeiten muss.


3