Die Python-Klasse erbt das Objekt

1244

Gibt es einen Grund, von einer Klassendeklaration zu erben object?

Ich habe gerade einen Code gefunden, der dies tut, und ich kann keinen guten Grund dafür finden.

class MyClass(object):
    # class code follows...
tjvr
quelle
2
Dadurch wird eine Klasse neuen Stils erstellt .
SLaks
116
Die Antwort auf diese Frage (obwohl einfach) ist ziemlich schwer zu finden. Wenn Sie Dinge wie "Python Object Base Class" oder ähnliches googeln, werden Seiten und Seiten mit Tutorials zur objektorientierten Programmierung angezeigt. Upvoting, weil dies der erste Link ist, der mich zu den Suchbegriffen "alte oder neue Python-Objekte" führte
überlegener

Antworten:

764

Gibt es einen Grund, von einer Klassendeklaration zu erben object?

In Python 3 gibt es außer der Kompatibilität zwischen Python 2 und 3 keinen Grund . In Python 2 viele Gründe .


Python 2.x Geschichte:

In Python 2.x (ab 2.2) gibt es zwei Arten von Klassen, abhängig von der Anwesenheit oder Abwesenheit objecteiner Basisklasse:

  1. "klassische" Stilklassen: Sie haben keine objectBasisklasse:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. "neue" Stilklassen: Sie haben direkt oder indirekt (z. B. von einem integrierten Typ geerbt ) objecteine Basisklasse:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)
    

Ohne Zweifel möchten Sie beim Schreiben einer Klasse immer Klassen neuen Stils wählen. Die Vorteile sind zahlreich, um einige davon aufzulisten:

  • Unterstützung für Deskriptoren . Insbesondere werden die folgenden Konstrukte mit Deskriptoren ermöglicht:

    1. classmethod: Eine Methode, die die Klasse als implizites Argument anstelle der Instanz empfängt.
    2. staticmethod: Eine Methode, die das implizite Argument nicht selfals erstes Argument empfängt .
    3. Eigenschaften mit property: Erstellen Sie Funktionen zum Verwalten des Abrufens, Festlegens und Löschens eines Attributs.
    4. __slots__: Spart den Speicherverbrauch einer Klasse und führt auch zu einem schnelleren Attributzugriff. Natürlich gibt es Einschränkungen .
  • Die __new__statische Methode: Mit dieser Option können Sie anpassen, wie neue Klasseninstanzen erstellt werden.

  • Method Resolution Order (MRO) : In welcher Reihenfolge werden die Basisklassen einer Klasse durchsucht, wenn versucht wird, die aufzurufende Methode aufzulösen.

  • Bezogen auf MRO, superAnrufe . Siehe auch super()super.

Wenn Sie nicht erben object, vergessen Sie diese. Eine ausführlichere Beschreibung der vorherigen Aufzählungspunkte sowie anderer Vorteile "neuer" Stilklassen finden Sie hier .

Einer der Nachteile von Klassen neuen Stils ist, dass die Klasse selbst mehr Speicher beansprucht. Wenn Sie jedoch nicht viele Klassenobjekte erstellen, bezweifle ich, dass dies ein Problem ist, und es ist ein negativer Untergang in einem Meer von Positiven.


Python 3.x Geschichte:

In Python 3 werden die Dinge vereinfacht. Es gibt nur Klassen neuen Stils (einfach als Klassen bezeichnet). Der einzige Unterschied beim Hinzufügen objectbesteht darin, dass Sie 8 weitere Zeichen eingeben müssen. Diese:

class ClassicSpam:
    pass

ist völlig gleichwertig (abgesehen von ihrem Namen :-) dazu:

class NewSpam(object):
     pass

und dazu:

class Spam():
    pass

Alle haben objectin ihrem __bases__.

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

Also, was solltest du tun?

In Python 2: immer objectexplizit von erben . Holen Sie sich die Vorteile.

In Python 3: Erben von, objectwenn Sie Code schreiben, der versucht, Python-unabhängig zu sein, das heißt, er muss sowohl in Python 2 als auch in Python 3 funktionieren. Andernfalls macht es keinen Unterschied, da Python ihn für Sie einfügt hinter den Kulissen.

Dimitris Fasarakis Hilliard
quelle
"abhängig vom Vorhandensein oder Fehlen eines eingebauten Typs als Basisklasse" => eigentlich geht es nicht um "Fehlen oder Vorhandensein eines eingebauten Typs als Basisklasse", sondern darum, ob die Klasse - direkt oder indirekt - von erbt object. IIRC Es gab einen Zeitpunkt, an dem noch nicht alle eingebauten Typen auf Klassen neuen Stils portiert wurden.
Bruno Desthuilliers
@brunodesthuilliers Mein Eindruck war, dass alle eingebauten Typen von geerbt haben object. Ich habe Python 2.2.3 in der Nähe und nach einer kurzen Überprüfung konnte ich keinen Täter finden, aber ich werde die Antwort später umformulieren, um es klarer zu machen. Wäre interessiert, wenn Sie ein Beispiel finden könnten, meine Neugier ist geweckt.
Dimitris Fasarakis Hilliard
Ehrlich gesagt (vgl. Das "IIRC" in meinem vorherigen Kommentar) bin ich mir in diesem Punkt nicht zu 101% sicher (ob alle eingebauten Typen bereits bei Einführung neuer Klassen in Klassen neuen Stils konvertiert wurden) - ich bin vielleicht einfach falsch, oder dies hat möglicherweise nur einige der Standardtypen der Bibliothek (aber nicht die eingebauten) betroffen. Aber ich denke, es sollte besser sein zu klären, was eine Klasse neuen Stils objectin ihren Basen hat.
Bruno Desthuilliers
7
Schade, dass Stackoverflow nur Upvote = Upvote + 1 für diese Art von Antworten macht. Ich wünschte, ich könnte Upvote machen + = N
PirateApp
1
staticmethodund classmethodfunktionieren auch in alten Klassen einwandfrei. propertysorta funktioniert zum Lesen in Klassen alten Stils, es kann jedoch keine Schreibvorgänge abfangen (wenn Sie also dem Namen zuweisen, erhält die Instanz ein Attribut des angegebenen Namens, das die Eigenschaft schattiert). Beachten Sie auch, dass es bei __slots__der Verbesserung der Attributzugriffsgeschwindigkeit hauptsächlich darum geht, den Verlust durch den Zugriff auf Klassenattribute neuen Stils rückgängig zu machen. Dies ist also kein Verkaufsargument für Klassen neuen Stils (die Speichereinsparungen sind jedoch ein Verkaufsargument).
ShadowRanger
540

Python 3

  • class MyClass(object): = Klasse neuen Stils
  • class MyClass:= Klasse neuen Stils (erbt implizit von object)

Python 2

  • class MyClass(object): = Klasse neuen Stils
  • class MyClass:= ALTE STILKLASSE

Erklärung :

Wenn Sie Basisklassen in Python 3.x definieren, dürfen Sie die objectaus der Definition entfernen. Dies kann jedoch die Tür für ein ernsthaft schwer zu verfolgendes Problem öffnen…

Python hat in Python 2.2 Klassen neuen Stils eingeführt, und mittlerweile sind Klassen alten Stils wirklich ziemlich alt. Die Diskussion über Klassen alten Stils ist in den 2.x-Dokumenten vergraben und in den 3.x-Dokumenten nicht vorhanden.

Das Problem ist, die Syntax für alten Stil Klassen in Python 2.x ist das gleiche wie die alternative Syntax für die neuen Stil - Klassen in Python 3.x . Python 2.x wird immer noch sehr häufig verwendet (z. B. GAE, Web2Py), und jeder Code (oder Codierer), der unbeabsichtigt Klassendefinitionen im 3.x-Stil in 2.x-Code einfügt, wird zu einigen ernsthaft veralteten Basisobjekten führen. Und weil Klassen im alten Stil nicht auf jedermanns Radar stehen, werden sie wahrscheinlich nicht wissen, was sie getroffen hat.

Also buchstabieren Sie es einfach auf lange Sicht und sparen Sie einigen 2.x-Entwicklern die Tränen.

Yarin
quelle
13
"Wenn Sie Basisklassen in Python 3.x definieren, dürfen Sie das Objekt aus der Definition entfernen. Dies kann jedoch die Tür für ein ernsthaft schwer zu verfolgendes Problem öffnen ..." Auf welche Probleme beziehen Sie sich?
Aidis
6
@Aidis: Ich denke, sie bedeuten, dass Code, der sowohl auf Py2 als auch auf Py3 ausgeführt wird, auf Py3 in Ordnung wäre, auf Py2 jedoch nicht funktioniert, wenn er auf neuen Klassenfunktionen basiert. Wenn ich persönlich solchen Code schreibe, lasse ich die explizite Vererbung weg und setze sie einfach __metaclass__ = typeoben in das Modul (nach der from __future__ import absolute_import, division, print_functionZeile :-)). Es ist ein Kompatibilitäts-Hack in Py2, der alle nachfolgend definierten Klassen im Modul standardmäßig neu gestaltet. In Py3 wird er vollständig ignoriert (nur eine zufällige globale Variable, die herumsteht), sodass er harmlos ist.
ShadowRanger
400

Ja, dies ist ein Objekt im neuen Stil. Es war eine in Python2.2 eingeführte Funktion.

Neue Art - Objekte haben ein anderes Objektmodell klassische Objekte, und einige Dinge nicht richtig mit altem Stil Objekten, zum Beispiel, arbeiten super(), @propertyund Deskriptoren. In diesem Artikel finden Sie eine gute Beschreibung einer neuen Stilklasse.

SO Link für eine Beschreibung der Unterschiede: Was ist der Unterschied zwischen alten und neuen Stilklassen in Python?

Jerub
quelle
110
+1 Dies. Beachten Sie, dass Klassen im alten Stil in Python 3 nicht mehr vorhanden sind, sodass Sie nur noch objectin Python 2 erben müssen .
9
Dies ist keine echte Antwort. ı verweist nur auf andere Artikel. Ich denke, Yarins Antwort sollte als Antwort auf diese Frage akzeptiert werden.
Alwbtc
2
@alwbtc: Diese Antwort hat auch etwas Neues. Zum Beispiel führte mich die Erwähnung von "super ()" zu einem anderen wichtigen [hier] ( stackoverflow.com/questions/576169/… ).
ViFI
34

Geschichte von Learn Python auf die harte Tour :

Pythons ursprüngliche Wiedergabe einer Klasse wurde in vielerlei Hinsicht gebrochen. Als dieser Fehler erkannt wurde, war es bereits zu spät und sie mussten ihn unterstützen. Um das Problem zu beheben, brauchten sie einen "neuen Klassen" -Stil, damit die "alten Klassen" weiter funktionieren, aber Sie können die neue, korrektere Version verwenden.

Sie beschlossen, ein Wort "Objekt" in Kleinbuchstaben als "Klasse" zu verwenden, von der Sie erben, um eine Klasse zu erstellen. Es ist verwirrend, aber eine Klasse erbt von der Klasse "Objekt", um eine Klasse zu erstellen, aber es ist kein Objekt, es ist wirklich eine Klasse, aber vergessen Sie nicht, vom Objekt zu erben.

Nur um Sie wissen zu lassen, was der Unterschied zwischen Klassen neuen Stils und Klassen alten Stils ist, erben Klassen neuen Stils immer von objectKlassen oder von einer anderen Klasse, die geerbt hat von object:

class NewStyle(object):
    pass

Ein weiteres Beispiel ist:

class AnotherExampleOfNewStyle(NewStyle):
    pass

Während eine Basisklasse im alten Stil so aussieht:

class OldStyle():
    pass

Und eine Kinderklasse im alten Stil sieht so aus:

class OldStyleSubclass(OldStyle):
    pass

Sie können sehen, dass eine Old Style-Basisklasse von keiner anderen Klasse erbt. Old Style-Klassen können jedoch natürlich voneinander erben. Das Erben vom Objekt garantiert, dass bestimmte Funktionen in jeder Python-Klasse verfügbar sind. In Python 2.2 wurden neue Stilklassen eingeführt

disp_name
quelle
8
Das Aufrufen der Root-Klasse objectist nicht allzu verwirrend, und tatsächlich ist es ziemlich normal. Smalltalk hat eine Root-Klasse mit dem Namen Objectund eine Root-Metaklasse mit dem Namen Class. Warum? Denn genau wie Dogeine Klasse für Hunde Objectist sie eine Klasse für Objekte und Classeine Klasse für Klassen. Java, C #, ObjC, Ruby und die meisten anderen klassenbasierten OO-Sprachen, die heutzutage verwendet werden und eine Root-Klasse haben, verwenden eine Variation des ObjectNamens, nicht nur Python.
Abarnert
30

Ja, es ist historisch . Ohne sie entsteht eine Klasse im alten Stil.

Wenn Sie type()ein Objekt im alten Stil verwenden, erhalten Sie nur "Instanz". Auf einem Objekt neuen Stils erhalten Sie dessen Klasse.

stricken
quelle
Wenn Sie type()eine Klasse im alten Stil verwenden, erhalten Sie außerdem "classobj" anstelle von "type".
Joel Sjögren
7

Die Syntax der Anweisung zur Klassenerstellung:

class <ClassName>(superclass):
    #code follows

Wenn keine anderen Oberklassen vorhanden sind, von denen Sie speziell erben möchten, superclasssollte dies immer der Fall sein object, der die Wurzel aller Klassen in Python darstellt.

objectist technisch gesehen die Wurzel von "New-Style" -Klassen in Python. Aber die Klassen im neuen Stil sind heute so gut wie der einzige Klassenstil.

Wenn Sie das Wort jedoch objectbeim Erstellen von Klassen nicht explizit verwenden , erbt Python 3.x, wie bereits erwähnt, implizit von der objectOberklasse. Aber ich denke explizit ist immer besser als implizit (Hölle)

Referenz

kmario23
quelle