Das hat mich immer verwirrt. Es scheint, als wäre das schöner:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
Als das:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
Gibt es einen bestimmten Grund dafür?
-
Erklärt zum einfachen Speichern und Verstehen, dass Sie einer Liste beitreten und in eine Zeichenfolge konvertieren. Sie ist ergebnisorientiert.str
zu implementieren, als sie auf jedem iterierbaren Typ zu implementieren.Antworten:
Dies liegt daran, dass jedes iterable Element verbunden werden kann (z. B. Liste, Tupel, Diktat, Set), aber das Ergebnis und der "Joiner" müssen Zeichenfolgen sein.
Zum Beispiel:
Wenn Sie etwas anderes als Zeichenfolgen verwenden, wird der folgende Fehler ausgegeben:
quelle
list.join(string)
erscheint eher als objektorientierter Ansatz,string.join(list)
klingt für mich jedoch viel prozeduraler.print(str.join('-', my_list))
und es funktioniert, fühlt sich besser an.__iter__
Methode definiert . Das Erfordernis, dass alle Iterables auch implementiert werden,join
würde eine allgemeine Schnittstelle (die auch Iterables über Nicht-Strings abdeckt) für einen ganz bestimmten Anwendungsfall komplizieren. Das Definierenjoin
auf Strins-Seitenschritten dieses Problems auf Kosten der "nicht intuitiven" Bestellung. Eine bessere Wahl wäre es gewesen, eine Funktion beizubehalten, wobei das erste Argument iterierbar und das zweite (optional) die Joiner-Zeichenfolge ist - aber dieses Schiff ist gesegelt.Dies wurde in den String-Methoden besprochen ... schließlich in das Python-Dev-Archiv eingefügt und von Guido akzeptiert. Dieser Thread begann im Juni 1999 und
str.join
war in Python 1.6 enthalten, das im September 2000 veröffentlicht wurde (und Unicode unterstützte). Python 2.0 (str
einschließlich unterstützter Methodenjoin
) wurde im Oktober 2000 veröffentlicht.str.join(seq)
seq.join(str)
seq.reduce(str)
join
als eingebaute Funktionlist
s,tuple
s, sondern alle Sequenzen / Iterables unterstützen.seq.reduce(str)
ist schwierig für Neuankömmlinge.seq.join(str)
führt eine unerwartete Abhängigkeit von Sequenzen zu str / unicode ein.join()
als eingebaute Funktion würde nur bestimmte Datentypen unterstützen. Die Verwendung eines integrierten Namespace ist also nicht gut. Wennjoin()
viele Datentypen unterstützt werden, wäre es schwierig, eine optimierte Implementierung zu erstellen. Wenn sie mit der__add__
Methode implementiert wird, ist sie O (n²).sep
) sollte nicht weggelassen werden. Explizit ist besser als implizit.In diesem Thread werden keine weiteren Gründe angegeben.
Hier sind einige zusätzliche Gedanken (meine eigenen und die meines Freundes):
Guidos Entscheidung wird in einer historischen Mail festgehalten und entscheidet über
str.join(seq)
:quelle
Weil sich die
join()
Methode in der Zeichenfolgenklasse befindet, anstatt in der Listenklasse?Ich bin damit einverstanden, dass es lustig aussieht.
Siehe http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
quelle
string
Bibliothek hat alle redundantenstr
Methoden entfernt, sodass Sie sie nicht mehr verwenden könnenstring.join()
. Persönlich hätte ich es nie für "lustig" gehalten, es macht vollkommen Sinn, da man viel mehr als nur Listen beitreten kann, aber der Schreiner ist immer eine Zeichenfolge!Ich stimme zu, dass es zunächst nicht intuitiv ist, aber es gibt einen guten Grund. Join kann keine Methode einer Liste sein, weil:
Es gibt tatsächlich zwei Join-Methoden (Python 3.0):
Wenn join eine Methode einer Liste wäre, müsste sie ihre Argumente überprüfen, um zu entscheiden, welche von ihnen aufgerufen werden soll. Und Sie können Byte und Str nicht zusammenfügen, daher ist die Art und Weise, wie sie es jetzt haben, sinnvoll.
quelle
Dies liegt daran, dass
join
es sich um eine "String" -Methode handelt! Es wird eine Zeichenfolge aus einer beliebigen iterierbaren Zeichenfolge erstellt. Wenn wir die Methode auf Listen setzen, was ist dann, wenn wir Iterables haben, die keine Listen sind?Was ist, wenn Sie ein Tupel von Zeichenfolgen haben? Wenn dies eine
list
Methode wäre, müssten Sie jeden solchen Iterator von Strings wielist
zuvor umwandeln, bevor Sie die Elemente zu einem einzigen String zusammenfügen könnten! Zum Beispiel:Lassen Sie uns unsere eigene List Join-Methode rollen:
Um es zu verwenden, müssen Sie zuerst eine Liste aus jeder Iterable erstellen, um die Zeichenfolgen in dieser Iterable zu verknüpfen, wodurch sowohl Speicher als auch Verarbeitungsleistung verschwendet werden:
Wir müssen also einen zusätzlichen Schritt hinzufügen, um unsere Listenmethode zu verwenden, anstatt nur die integrierte String-Methode zu verwenden:
Leistungsbeschränkung für Generatoren
Der Algorithmus, mit dem Python die endgültige Zeichenfolge erstellt,
str.join
muss die iterierbare Zeichenfolge tatsächlich zweimal durchlaufen. Wenn Sie ihm also einen Generatorausdruck bereitstellen, muss er zuerst in einer Liste materialisiert werden, bevor die endgültige Zeichenfolge erstellt werden kann.Während das Weitergeben von Generatoren normalerweise besser ist als das Listenverständnis,
str.join
ist dies eine Ausnahme:Trotzdem ist die
str.join
Operation immer noch semantisch eine "String" -Operation, so dass es immer noch sinnvoll ist, sie auf demstr
Objekt zu haben als auf verschiedenen iterablen.quelle
Betrachten Sie es als die natürliche orthogonale Operation zum Teilen.
Ich verstehe, warum es auf alles Iterierbare anwendbar ist und daher nicht einfach nur auf der Liste implementiert werden kann .
Aus Gründen der Lesbarkeit würde ich es gerne in der Sprache sehen, aber ich denke nicht, dass dies tatsächlich machbar ist. Wenn die Iterierbarkeit eine Schnittstelle wäre, könnte sie der Schnittstelle hinzugefügt werden, aber es handelt sich nur um eine Konvention, und daher gibt es keinen zentralen Weg dazu Fügen Sie es der Menge der Dinge hinzu, die iterierbar sind.
quelle
In erster Linie, weil das Ergebnis von a
someString.join()
eine Zeichenfolge ist.Die Sequenz (Liste oder Tupel oder was auch immer) erscheint nicht im Ergebnis, sondern nur als Zeichenfolge. Da das Ergebnis eine Zeichenfolge ist, ist es als Methode einer Zeichenfolge sinnvoll.
quelle
-
in "-". join (my_list) deklariert, dass Sie eine Liste aus dem Verknüpfen von Elementen in eine Zeichenfolge konvertieren. Sie ist ergebnisorientiert (nur zum einfachen Speichern und Verstehen).Ich mache ein ausführliches Cheatsheet von Methods_of_string als Referenz.
quelle
Beide sind nicht nett.
string.join (xs, delimit) bedeutet, dass das String-Modul die Existenz einer Liste kennt, über die es nichts zu wissen hat, da das String-Modul nur mit Strings arbeitet.
list.join (delimit) ist ein bisschen netter, weil wir es so gewohnt sind, dass Strings ein grundlegender Typ sind (und das sind sie auch). Dies bedeutet jedoch, dass Join dynamisch versendet werden muss, da im beliebigen Kontext von
a.split("\n")
ausgelöst werden muss, Python-Compilers möglicherweise nicht bekannt ist, was ein ist, und es nachschlagen muss (analog zur vtable-Suche), was teuer ist, wenn Sie es häufig tun mal.Wenn der Python-Laufzeit-Compiler weiß, dass list ein integriertes Modul ist, kann er die dynamische Suche überspringen und die Absicht direkt in den Bytecode codieren, während er andernfalls "join" von "a" dynamisch auflösen muss, was mehrere Ebenen umfassen kann der Vererbung pro Aufruf (da sich zwischen den Aufrufen die Bedeutung des Joins möglicherweise geändert hat, da Python eine dynamische Sprache ist).
Leider ist dies der ultimative Fehler der Abstraktion. Unabhängig davon, für welche Abstraktion Sie sich entscheiden, ist Ihre Abstraktion nur im Kontext des Problems sinnvoll, das Sie lösen möchten, und als solches können Sie niemals eine konsistente Abstraktion haben, die nicht mit den zugrunde liegenden Ideologien unvereinbar wird, wenn Sie anfangen, sie zu verkleben zusammen, ohne sie in eine Ansicht zu verpacken, die Ihrer Ideologie entspricht. Wenn Sie dies wissen, ist der Ansatz von Python flexibler, da er billiger ist. Sie müssen mehr bezahlen, damit er "schöner" aussieht, indem Sie entweder Ihren eigenen Wrapper oder Ihren eigenen Präprozessor erstellen.
quelle
Die Variablen
my_list
und"-"
sind beide Objekte. Insbesondere sind sie Instanzen der Klassenlist
undstr
, respectively. Diejoin
Funktion gehört zur Klassestr
. Daher ist die Syntax"-".join(my_list)
wird benutzt , weil das Objekt"-"
nimmtmy_list
als eine Eingabe.quelle