2010-09-14 4 views
6

Sets und Listen werden in Python anders gehandhabt, und es scheint keinen einheitlichen Weg zu geben, mit beiden zu arbeiten. Das Hinzufügen eines Elements zu einer set erfolgt beispielsweise mit der Methode add und für die list mit der Methode append. Ich bin mir bewusst, dass es verschiedene Semantiken gibt, aber es gibt auch gemeinsame Semantiken, und oft kümmert sich ein Algorithmus, der mit einer Sammlung arbeitet, eher um die Gemeinsamkeiten als um die Unterschiede. Die C++ - STL zeigt, dass dies funktionieren kann. Warum gibt es in Python kein solches Konzept?Warum werden Sammlungen in Python nicht einheitlich behandelt?

Bearbeiten: In C++ kann ich eine output_iterator verwenden, um Werte in einer (fast) beliebigen Art von Sammlung, einschließlich Listen und Mengen zu speichern. Ich kann einen Algorithmus schreiben, der einen solchen Iterator als Argument akzeptiert und Elemente darauf schreibt. Der Algorithmus ist dann völlig agnostisch für die Art des Containers (oder eines anderen Geräts, kann eine Datei sein), die den Iterator unterstützt. Wenn der Sicherungscontainer ein Satz ist, der Duplikate ignoriert, dann ist dies die Entscheidung des Aufrufers. Mein spezifisches Problem ist, dass es mir jetzt mehrere Male passiert ist, dass ich zum Beispiel eine list für eine bestimmte Aufgabe verwendet habe und später entschied, dass set geeigneter ist. Jetzt muss ich die append zu add an mehreren Stellen in meinem Code ändern. Ich frage mich nur, warum Python kein Konzept für solche Fälle hat.

+1

"Sets und Listen werden in Python anders behandelt, weil sie ** im Wesentlichen ** anders sind. Sie können nicht "einheitlich" gemacht werden, weil - nun - sie sind so verschieden wie Fließkomma und Datei. "Ich bin mir bewusst, dass es unterschiedliche Semantiken gibt". Okay. Wonach fragst du? Speziell? Können Sie detailliertere Beispiele für Ihre Meinung geben? –

+0

@ S.Lott: Ich habe ein Beispiel und einige Erläuterungen hinzugefügt. –

+0

"Ein Satz, der Duplikate ignoriert"? Was? Was ist das? Ein Set kann per Definition keine Duplikate haben. Ich verstehe nicht, wonach du fragst. –

Antwort

6

Die direkte Antwort: es ist ein Designfehler.

Sie sollten in der Lage sein, in jeden Container einzufügen, in dem eine generische Einfügung (z. B. mit Ausnahme von dict) mit demselben Methodennamen sinnvoll ist. Es sollte einen konsistenten, generischen Namen für die Einfügung geben, z. add, entsprechend set.add und list.append, so können Sie zu einem Container hinzufügen, ohne sich so sehr darum kümmern zu müssen, in was Sie einfügen. Die Verwendung unterschiedlicher Namen für diese Operation in unterschiedlichen Typen ist eine grundlose Inkonsistenz und stellt einen schlechten Basisstandard dar: Die Bibliothek sollte Benutzercontainer dazu ermutigen, eine konsistente API zu verwenden, anstatt für jeden Basiscontainer weitgehend inkompatible APIs bereitzustellen.

Das heißt, es ist nicht oft ein praktisches Problem in diesem Fall: die meisten der Zeit, wo die Ergebnisse einer Funktion sind eine Liste von Elementen, implementieren Sie es als Generator. Sie ermöglichen die Handhabung beides konsequent (aus der Sicht der Funktion), sowie andere Formen der Iteration:

def foo(): 
    yield 1 
    yield 2 
    yield 3 

s = set(foo()) 
l = list(foo()) 
results1 = [i*2 for i in foo()] 
results2 = (i*2 for i in foo()) 
for r in foo(): 
    print r 
+1

+1 für den Generator. –

+0

Nun, Python will explizit sein, also versuche einfach, ein Verb zu schreiben, das "Ordnung bewahren" (für Listen) und "nicht Ordnung bewahren" (für Mengen), gleichzeitig! Ziemlich unmöglich ;-P Aber wie Sie gesagt haben, gibt es tatsächlich einen einheitlichen Weg, Sätze und Listen zu konstruieren, und es ist viel mehr pythonisch, als 'add' oder' append' aufzurufen. +1 dafür. –

+0

Vielleicht ist es nicht so sehr ein Designfehler als eine andere Art zu denken. In der C++ - Standardbibliothek akzeptiert eine Funktion, die Werte erzeugt, einen Ausgabe-Iterator. In Python wird eine Funktion, die Werte erzeugt, zu einem Generator gemacht. Wenn Sie möchten, dass Python sich mehr wie die C++ - Standardbibliothek verhält, können Sie eine OutputIterator-Klasse erstellen, die verschiedene Containertypen in ihrem Konstruktor akzeptiert und ermittelt, welche Methode für jeden Container aufgerufen wird. Sie würden es wie folgt verwenden: my_func (iter, OutputIterator (mein_container)) –

4

hinzufügen und anhängen sind anders. Sets sind ungeordnet und enthalten eindeutige Elemente, während append andeutet, dass das Element immer hinzugefügt wird und dass dies speziell am Ende geschieht.

Sätzen und Listen können beide als iterable behandelt werden, und das ist ihre gemeinsame Semantik, und das ist frei von Ihren Algorithmen.

Wenn Sie einen Algorithmus haben, der von einer Art Addition abhängt, können Sie einfach nicht auf Mengen, Tupel, Listen, Dicts, Strings, die sich gleich verhalten.

+1

+1: 'hinzufügen 'zu einem Set hat möglicherweise keinen Effekt. An eine Liste "anhängen" hat immer einen Effekt. Und Listen haben 'extend' - was bedeutet das für ein Set? "Gewerkschaft" vielleicht? Die Semantik ist völlig anders. –

+0

Das gleiche gilt für Mengen in C++, aber sie haben ein einheitliches Konzept zum Hinzufügen von Elementen (siehe Bearbeiten meiner Frage). –

+0

STL bietet * viele * Containertypen scheint es. Ich kann mir vorstellen, dass Sie dort eine Vereinfachung wünschen. Soweit ich das beurteilen kann, ist Ihre Frage nur relevant für Listen und Sets, wenn es um Python geht. Wenn Sie das wirklich brauchen, können Sie immer einen eigenen Wrapper schreiben, der Listen und Sets umschließt und sich so verhält, wie Sie es wollen. –

1

Der eigentliche Grund wahrscheinlich nur zu Python Geschichte zusammenhängt.

Der integrierte Settyp war nicht built-in until Python 2.6 und basierte auf einem Mengenmodul, das selbst erst Python 2.3 in der Standardbibliothek war. Offensichtlich könnte das Ändern der Semantik des Settyps eine Menge vorhandenen Codes zerstören, der sich auf das Modul der ursprünglichen Sätzen stützt, und im Allgemeinen scheuen Sprachdesigner davor, bestehenden Code ohne eine Veröffentlichung einer Major-Nummer zu brechen.

Sie können den ursprünglichen Autor des Moduls beschuldigen, wenn Sie möchten, aber bedenken Sie, dass benutzerdefinierte Typen und integrierte Typen notwendigerweise in verschiedenen Universen bis Python 2.2 lebten, was bedeutete, dass Sie ein eingebautes Programm nicht direkt erweitern konnten Typ, und wahrscheinlich erlaubte es Modulautoren, sich damit einverstanden zu fühlen, konsistente Sammlungssemantik nicht aufrechtzuerhalten.

Verwandte Themen