2010-10-15 6 views
17

Ich war vor kurzem über ein Coding-Problem, das ich hatte und jemand sah auf den Code sagte, dass Subclassing-Liste schlecht war (mein Problem war unabhängig von dieser Klasse). Er sagte, dass du es nicht tun solltest und dass es mit einer Reihe von schlechten Nebenwirkungen verbunden war. Ist das wahr?Was ist vor der Unterklassenliste zu beachten?

Ich frage, ob Liste ist in der Regel Unterklasse schlecht und wenn ja, was sind die Gründe. Alternativ, was sollte ich beachten, bevor ich die Liste in Python ablege?

+2

Subclassing-Liste ist nicht von Natur aus schlecht, aber es gibt viele Fälle, in denen es wirklich nicht das ist, was Sie tun möchten. Wir können nicht beantworten, ob das der Fall ist, es sei denn, Sie geben uns Einzelheiten. –

Antwort

17

Es gibt keine Vorteile für Unterklassen list. Keine der Methoden verwendet Methoden, die Sie überschreiben, sodass unerwartete Fehler auftreten können. Darüber hinaus ist es sehr oft verwirrend Dinge wie self.append anstelle von self.foos.append oder speziell self[4] anstelle von self.foos[4] zu tun, um auf Ihre Daten zuzugreifen. Sie können etwas machen, das funktioniert genau wie eine Liste oder (besser) jedoch wie eine Liste, die Sie wirklich möchten während nur Unterklassen object.

+3

Was ist, wenn wir einer Liste ein Attribut hinzufügen wollen? Angenommen, wir haben mylist = []. Wir wollen etwas wie mylist.x = 3. – riza

+1

@Selinap, In einem Fall, in dem ich wollte, dass mein Zustand eine Liste von etwas und ein int enthält, würde ich wahrscheinlich immer noch Zusammensetzung verwenden. Die Verwendung von Vererbung führt zu Verwirrung beim Schreiben, Verwirrung bei der Verwendung und bringt Ihnen nichts wirklich. –

+2

Dies scheint Python 3 nicht zu entsprechen. Diese enthalten ['collections.UserList'] (https://docs.python.org/3.4/library/collections.html#collections.UserList) explizit für diesen Zweck. Es schlägt sogar vor, dass eine Unterklassenbildung von der Liste jetzt möglich ist: "Die Notwendigkeit für diese Klasse wurde teilweise durch die Fähigkeit ersetzt, direkt von der Unterklasse abzurücken;" (Ich verstehe, dies ist ein altes Thema und die obigen Kommentare waren wahrscheinlich wahr, während Sie geschrieben haben, wollen dies klar machen für Leute, die diese Frage jetzt finden) – Claude

11

Ich denke, die erste Frage, die ich mir stellen würde, ist: "Ist mein neues Objekt wirklich eine Liste?". Geht es wie eine Liste, rede wie eine Liste? Oder ist es etwas anderes?

Wenn es sich um eine Liste handelt, sollten alle Standardlistenmethoden sinnvoll sein.

Wenn die Standardlistenmethoden keinen Sinn ergeben, sollte Ihr Objekt eine Liste enthalten und keine Liste sein.

In der alten Python (2.2?) Sub-Classing-Liste war aus verschiedenen technischen Gründen eine schlechte Idee, aber in einem modernen Python ist es in Ordnung.

+4

+1 Nur erben, wenn es wirklich 100% Sinn macht, sonst komponieren. – delnan

+0

Was die Nebenwirkungen angeht, war er etwas veraltet? Die Daten sind in einer Liste enthalten, aber es gibt eine Menge anderer spezifischer Methoden, die ich über die Spitze werfen muss, um eine Reihe von Dingen zu erledigen. –

+0

ja, erben für "ist-a" Beziehungen, komponieren für so ziemlich alles andere. –

6

Nick ist richtig. Auch wenn ich nicht mit Python sprechen kann, in anderen OO-Sprachen (Java, Smalltalk) ist das Unterklassifizieren einer Liste eine schlechte Idee. Vererbung im Allgemeinen sollte vermieden werden und Delegationszusammensetzung stattdessen verwendet werden.

Stattdessen erstellen Sie eine Containerklasse und delegieren Anrufe an die Liste. Die Containerklasse hat einen Verweis auf die Liste, und Sie können die Aufrufe und die Rückgabe der Liste sogar in Ihren eigenen Methoden verfügbar machen. Dies bietet zusätzliche Flexibilität und ermöglicht es Ihnen, die Implementierung (einen anderen Listentyp oder eine andere Datenstruktur) später zu ändern, ohne Code zu beschädigen. Wenn Sie möchten, dass Ihre Liste verschiedene Dinge vom Typ listy ausführt, kann Ihr Container dies tun und die einfache Liste als einfache Datenstruktur verwenden. Stellen Sie sich vor, Sie hätten 47 verschiedene Listen verwendet. Wollen Sie wirklich 47 verschiedene Unterklassen pflegen? Stattdessen könnten Sie dies über den Container und die Schnittstellen tun. Eine Klasse, die es ermöglicht, dass Benutzer Ihre neuen und verbesserten Methoden über die Schnittstelle (n) aufrufen und zulassen können, wobei die Implementierung verborgen bleibt.

17

Die abstract base classes im Modul collections, insbesondere MutableSequence, kann nützlich sein, wenn list-ähnliche Klassen implementiert werden. Diese sind in Python 2.6 und höher verfügbar.

Mit ABCs können Sie die "Kern" -Funktionalität Ihrer Klasse implementieren und es werden die Methoden zur Verfügung gestellt, die logisch davon abhängen, was Sie definiert haben.

Zum Beispiel wird __getitem__ in einer collections.Sequence abgeleiteten Klasse Implementierung genug sein, um die Klasse zu schaffen, mit __contains__, __iter__ und anderen Methoden.

Sie können immer noch ein enthaltenes Listenobjekt verwenden, um das Heavy Lifting durchzuführen.

+1

Seit Python 3.3+ wurde es in das Modul ['collections.abc'] (https://docs.python.org/3/library/collections.abc.html) verschoben. – xmedeko