Konkrete Beispiele für Pythons Maxime "Nur eine Möglichkeit" [closed]

34

Ich lerne Python und bin fasziniert von dem folgenden Punkt in PEP 20 The Zen of Python :

Es sollte einen - und am besten nur einen - offensichtlichen Weg geben, dies zu tun. Obwohl dieser Weg auf den ersten Blick nicht offensichtlich ist, es sei denn, Sie sind Holländer.

Kann jemand konkrete Beispiele für diese Maxime nennen? Besonders interessiert mich der Kontrast zu anderen Sprachen wie Ruby. Ein Teil der Ruby-Designphilosophie (ich glaube, sie hat ihren Ursprung in Perl) ist, dass mehrere Möglichkeiten, dies zu tun, eine gute Sache sind. Kann jemand einige Beispiele nennen, die die Vor- und Nachteile der einzelnen Ansätze aufzeigen? Beachten Sie, ich bin nicht nach einer Antwort, die besser ist (was wahrscheinlich zu subjektiv ist, um jemals beantwortet zu werden), sondern nach einem unvoreingenommenen Vergleich der beiden Stile.

Charles Roper
quelle

Antworten:

47

Im Vergleich zu Sprachen wie Perl verfügt Python über eine begrenzte Anzahl von Steuerungskonstrukten:

  • nur ifund nein unless,
  • nur, fordass über Sequenzen iteriert und keine foreachoder C-Stil for,
  • nur whiledas prüft eine Bedingung jede Schleife und nein do-while,
  • nur if-elifund nein switch,
  • Es gibt nur ein Kommentar-Konstrukt, das #, und für jede Zeile können Sie feststellen, ob sie auskommentiert ist oder nicht, ohne vorhergehende Zeilen zu betrachten.

Es gibt auch fast eine Möglichkeit, Ihre Quelle einzurücken. Die meisten Fälle von kreativen Einrückungen werden syntaktisch ausgeschlossen.

Dies erleichtert dem Menschen das Parsen einer Python-Quelle.

Es gibt Versuche, in integrierten Typen und in der Standardbibliothek minimal, aber vollständig zu sein.

  • Für veränderbare Listen verwenden Sie den einzigen integrierten listTyp. es ist O (1) für die meisten Operationen, und Sie müssen nie die richtige Implementierung wählen,
  • für unveränderliche Listen verwenden Sie ebenfalls nur den tupleTyp,
  • Für Karten verwenden Sie die einzige integrierte Funktion, dictdie in den meisten Fällen verdammt effizient ist. Sie müssen nicht überlegen, welche Implementierung verwendet werden soll.

Python 3 erweitert dies auf Ganzzahlen: Egal wie groß Ihre Ganzzahl ist, Sie verwenden denselben Typ und kümmern sich nie um Zwang.

Python versucht, syntaktischen Zucker zu vermeiden. Aber manchmal wird syntaktischer Zucker hinzugefügt, um den offensichtlichen Weg zu verdeutlichen. Sie können schreiben, if foo is not Noneanstatt zu schreiben, if not (foo is None)weil "nicht" ein Sonderfall ist. Noch foo is not Noneliest leicht, nicht falsch interpretiert werden kann, und Sie müssen nicht denken, schreiben Sie einfach die offensichtliche Sache.

Natürlich, die meisten von komplexeren Dinge in Python kann auf verschiedene Weise erfolgen. Sie können Klassen Methoden durch Deklaration oder durch einfache Zuweisung von Slots hinzufügen, Sie können Argumente auf verschiedene kreative Arten an Funktionen übergeben usw. Dies liegt nur daran, dass die Interna der Sprache meistens offengelegt werden.

Der Schlüssel ist, dass es immer einen Weg gibt, der der beste sein soll, den allumfassenden Fall. Wenn es andere Möglichkeiten gibt, wurden sie nicht als gleichwertige Alternativen hinzugefügt (wie ifund unless), sondern legen lediglich das Innenleben offen. Langsam aber stetig werden solche Alternativen durch die Verbesserung des bekannten besten Mechanismus überholt (nicht beseitigt!).

Dekorateure schließen AOP-Funktionsaufrufe ab. Vor 2.6 mussten Sie __metaclass__magic member verwenden, um die Metaklasse einer Klasse zu deklarieren. Jetzt können Sie auch hier die gleiche Decorator-Syntax verwenden. Vor 3.0 hatten Sie zwei Arten von Zeichenfolgen, byteorientiert und Unicode, die Sie versehentlich mischen konnten. Jetzt haben Sie den einzigen Unicode strund den einzigen binären transparenten Code bytes, den Sie nicht versehentlich mischen können.

9000
quelle
3
Vergessen Sie nur als Hinweis nicht die """Kommentare (docstrings). Diese erstrecken sich über mehrere Zeilen.
Asthasr
8
Literale mit dreifachen Anführungszeichen sind nur Zeichenfolgen, die mit einfachen Anführungszeichen identisch sind, können jedoch mehrere Zeilen umfassen, ohne dass Zeilenenden maskiert werden. Ein Zeichenfolgenliteral direkt nach der Deklaration wird als Dokumentzeichenfolge betrachtet und ist kein Kommentar. Normalerweise kann auf es als __doc__Attribut zugegriffen werden. Aber Strings ist ein Bereich, in dem Python definitiv viele "richtige Wege" bietet: Verwenden Sie einfache, doppelte oder dreifache Anführungszeichen, verbinden Sie implizit benachbarte Literale, verwenden Sie rfür unformatierte Literale usw.
9000
1
Ich denke, @ syrions Kommentar betraf "Sie können immer entscheiden, ob eine Zeile kommentiert wird oder nicht, indem Sie sie nur
ansehen
2
"Dies macht das Parsen einer Python-Quelle für Menschen einfacher." <- das ist subjektiv
jiggy
Wie hat sich die Metaklassendeklaration in 2.7 geändert? Das Dekorationsmuster kann in den 2.7-Dokumenten für Metaklassen nicht gefunden werden.
Nick T
10

Weitere Beispiele sind:
len()Ist eine Funktion anstelle einer Methode in jeder Sequenz vorhanden? wenn Sie mit Java vergleichen haben Sie .length, .size(), .getSize(), und andere Methoden , um die Anzahl der Elemente in einer Sequenz zu finden.

Ein weiteres Beispiel ist die Tatsache, dass .join()es sich um eine stringMethode handelt, nicht um eine Methode, die in jeder Sequenz vorhanden ist. Sie müssen nicht wissen, ob der Join-Parameter eine Liste, eine Menge, ein Verständnis oder was auch immer ist, es wird funktionieren.

Vito De Tullio
quelle
8

In C gibt es viele Möglichkeiten, den Wert einer Variablen um eins zu erhöhen:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

Jedes erhöht den Wert von ium 1, aber jedes ist etwas anders.

In Python gibt es wirklich nur einen Weg; füge einfach einen hinzu.

i += 1

Und während es mehr als eine syntaktisch gültige Möglichkeit gibt, dies zu tun (z. B. i = i + 1), tun Sie dasselbe mit denselben Nebenwirkungen.


quelle
1
Ich bin kein Experte, aber dieses Beispiel scheint genau die "einzige Möglichkeit, es zu tun" -Idee zu verletzen. Wir haben zwei Möglichkeiten, aber welche ist die offensichtlichere? Für mich ist das erste Beispiel offensichtlicher, während das zweite etwas knapper, aber für jeden Programmierer, der über die Grundlagen hinausgegangen ist, nicht weniger lesbar oder offensichtlich ist. Vielen Dank für Ihre Antwort - es ist ein guter Anlass zum Nachdenken.
Charles Roper
@Peter (und @Charles): Eigentlich i = i + 1handelt es sich um eine Zuweisung, nicht um ein Inkrement. In Python ist ein Inkrement i += 1. In C-Stil Sprachen können Sie schreiben i++, ++iund i += 1.
Josh K
2
Sie sind sich nicht sicher, was Ihren "viel Verwirrung" -Kommentar angeht. Alle drei Ihrer C-Beispiele (Sie haben es verpasst i += 1, übrigens) liefern genau das gleiche Ergebnis. Ich sehe nur, dass Leute verwirrt sind, wenn sie eine Variable als Teil eines größeren Ausdrucks vor oder nach dem Inkrementieren verwenden. Dies lässt sich normalerweise schnell beheben, indem Sie den entsprechenden Abschnitt der Sprachreferenz lesen. Persönlich hätte ich die Tatsache herausgegriffen, dass man mit beiden str[4]oder auf das fünfte Zeichen einer Zeichenfolge verweisen kann *(str+4), aber vielleicht war das zu einfach ...
TMN
2
@TMN: Einige Fälle wie max(i++, ++i)können nicht schnell behoben werden. C hat viele "undefinierte" und "implementierungsabhängige" Verhaltensfälle, alle aus gutem Grund - aber jeder kann eine Falle schaffen.
9000
@TMN: Ganz zu schweigen von 4 [str] (gültig in C, möglicherweise nicht gültig in C ++).
Vatine
6

Eine andere Möglichkeit könnten Listenverständnisse sein. In Python können Sie dies tun:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

Aber der "naheliegende" Weg (wenn Sie Holländer sind oder mit Python besser vertraut sind), dies zu tun, wäre ein Listenverständnis:

new_list = [item for item in list_of_items if item < 10]

Es ist kürzer, die new_list wird in einem Schritt erstellt, läuft meiner Meinung nach schneller und ist elegant. Auf der anderen Seite könnte man argumentieren, dass es sich weniger explizit anfühlt, aber ich denke, wenn man sich erst einmal daran gewöhnt hat, ist es genauso explizit.

Chelonian
quelle
Einrückung und Code: Stellen Sie 4 Leerzeichen voran, dann wird die Einrückung beachtet.
Inca