Warum teilen Python-Generatoren und -Funktionen das Schlüsselwort "def"?

10

Folgendes berücksichtigen:

def some_function():
    return 1

def some_generator():
    yield 1

Im obigen Code some_functionist eine Funktion, während some_generatores sich um einen Generator handelt. Sie sehen ziemlich ähnlich aus.

Das Problem beim Lesen von Code ist, dass ich jede Zeile in einer "Funktion" nach dem yieldSchlüsselwort durchsuchen muss, bevor ich feststellen kann, ob es sich tatsächlich um eine Funktion oder einen Generator handelt!

Es scheint mir nur, dass die Verwendung eines anderen Schlüsselworts für Generatoren sinnvoller wäre, z.

gen some_generator():
    yield 1

Was sind die Vorteile der Verwendung des defSchlüsselworts für Generatoren und Funktionen? Warum wurde kein neues Schlüsselwort eingeführt, um Funktionen und Generatoren zu trennen?

Derek Kwok
quelle
Ich kenne die wahre Antwort nicht, aber ich beginne oft damit, Funktionen zu schreiben, die Listen zurückgeben, und konvertiere sie dann in Generatoren, wenn es richtig erscheint. Die Übereinstimmung der Syntax macht dies natürlicher.
Gort den Roboter
2
@StevenBurnap Dereks Vorschlag, etwas genanstelle von zu verwenden, defwürde diese Transformation nicht wesentlich belastender machen.
Jamesdlin
1
Im Allgemeinen versuchen Sprachdesigner, das Hinzufügen unnötiger Schlüsselwörter zu vermeiden. Jedes hinzugefügte Schlüsselwort ist eine Kennung, die Programme nicht für andere Zwecke verwenden dürfen.
Jamesdlin
@jamesdlin: Aber die Frage ist, dass ein neues Schlüsselwort notwendig wäre .
Giorgio
1
@jamesdlin: Natürlich können Sie Funktionen und Generatoren anhand ihres Körpers unterscheiden, aber die Frage besagt, dass die Verwendung unterschiedlicher Schlüsselwörter den Code lesbarer machen würde.
Giorgio

Antworten:

14

"Was sind die Vorteile der Verwendung des Schlüsselworts def für Generatoren und Funktionen?"

Während sie sich mechanisch unterscheiden, sind sie in der Praxis, wenn ich sie benutze, für mich konzeptionell oft gleich (ich denke nicht viel darüber nach, range()vs zu nennen xrange()).

Um schnell zu verstehen, worum es bei der Funktion geht, stimme ich zu, dass bei der Verwendung von etwas verloren geht def, aber die Dinge sollten innerhalb der Funktion zunächst nicht zu verschleiert sein.

Sogar ein Impliziter return Nonekann das beabsichtigte Verhalten einer Funktion nach einer langen Reihe von Bedingungen verwirren (wie in, war ein return Nonebeabsichtigtes Verhalten oder ein Versehen in der Logik). Aber das sind nur meine Überzeugungen darüber.

Ich glaube nicht, dass meine Argumentation besonders überzeugend ist, deshalb werde ich mich nur PEP 255 zuwenden :

Problem: Fügen Sie anstelle von "def" ein anderes neues Schlüsselwort (z. B. "gen" oder "generator") ein oder ändern Sie auf andere Weise die Syntax, um Generatorfunktionen von Nicht-Generatorfunktionen zu unterscheiden.

Con: In der Praxis (wie Sie über sie denken), Generatoren sind Funktionen, aber mit dem Drall , dass sie fortsetzbar. Die Mechanik ihrer Einrichtung ist ein vergleichsweise kleines technisches Problem, und die Einführung eines neuen Schlüsselworts würde die Mechanik des Starts von Generatoren (ein wichtiger, aber winziger Teil des Lebens eines Generators) nicht überbetonen.

Pro: In Wirklichkeit (wie Sie über sie denken) sind Generatorfunktionen tatsächlich Fabrikfunktionen, die Generator-Iteratoren wie von Zauberhand erzeugen. In dieser Hinsicht unterscheiden sie sich radikal von Nicht-Generator-Funktionen und verhalten sich eher wie ein Konstruktor als wie eine Funktion. Die Wiederverwendung von "def" ist daher bestenfalls verwirrend. Eine im Körper vergrabene "Yield" -Anweisung ist nicht genug Warnung, dass die Semantik so unterschiedlich ist.

BDFL: "def" bleibt es. Kein Argument auf beiden Seiten ist absolut überzeugend, daher habe ich die Intuition meines Sprachdesigners konsultiert. Es sagt mir, dass die im PEP vorgeschlagene Syntax genau richtig ist - nicht zu heiß, nicht zu kalt. Aber wie das Orakel bei Delphi in der griechischen Mythologie sagt es mir nicht warum, so dass ich keine Gegenargumente für die Argumente gegen die PEP-Syntax habe. Das Beste, was ich mir einfallen lassen kann (abgesehen davon, dass ich den bereits gemachten Widerlegungen zustimme), ist "FUD". Wenn dies vom ersten Tag an Teil der Sprache gewesen wäre, bezweifle ich sehr, dass es Andrew Kuchlings "Python Warts" -Seite gemacht hätte.

Quaspas
quelle
1
Es ist erwähnenswert, dass für die in PEP 492 hinzugefügten neuen await(und async withund async for) Syntaxkonstrukte , die sehr ähnlich yield fromfunktionieren, die Deklaration der Funktion, in der sie verwendet werden, async defanstelle von just erforderlich ist def.
Feuermurmel
2
  1. Durch das Hinzufügen neuer Schlüsselwörter besteht die Gefahr, dass vorhandene Programme beschädigt werden. Sprachdesigner versuchen im Allgemeinen, das Hinzufügen neuer Schlüsselwörter zu vermeiden, insbesondere bei Sprachfunktionen, die hinzugefügt werden, nachdem die Sprache bereits an Popularität gewonnen hat. Jedes hinzugefügte Schlüsselwort ist eine Kennung, die Programme nicht für andere Zwecke verwenden dürfen. Das Hinzufügen eines Schlüsselworts kann daher möglicherweise vorhandene Programme beschädigen. Sprachdesigner müssen die Vorteile eines neuen Keywords gegen die Kosten abwägen.

  2. Ich bezweifle, dass das Definieren eines separaten Schlüsselworts für Generatoren von großem Nutzen wäre. Zu verstehen, ob ein Symbol dem Namen einer Funktion oder dem Namen eines Generators entspricht, ist für Anrufer wichtig, und Anrufer sollten nicht (und manchmal auch nicht) prüfen müssen, welches Schlüsselwort zur Implementierung verwendet wurde. Dies liegt in der Verantwortung besserer Namenskonventionen und Dokumentationen.

Jamesdlin
quelle
1

Generatoren sind Funktionen, die träge auswerten. Da sie an der Basis dasselbe sind, ist es sinnvoll, dass sie dasselbe Schlüsselwort verwenden. Eine Möglichkeit könnte darin bestehen, einen Kommentar zu verwenden, um zu identifizieren, welcher für eine bestimmte Instanz welcher ist:

def some_function(): #This is a function.
    return 1

def some_generator(): #This is a generator.
    yield 1
Weltingenieur
quelle
0

Ich würde vermuten, dass es mehr pythonisch ist, aber was weiß ich? ;)

Ich denke nicht wirklich, dass es so wichtig ist. Es fällt mir leichter, mich zu erinnern, weil ich mir beide nicht merken muss.

EDIT: Der PEP könnte sagen, Sie könnten dort untersuchen.

XiKuuKy
quelle
Vielen Dank! In der Tat sagt der PEP! In PEP-255 finden Sie die Vor- und Nachteile sowie die endgültige Entscheidung bezüglich eines neuen Schlüsselworts für Generatoren.
Derek Kwok
Mit pythonischer Bedeutung: "Wie es in Python gemacht wird"?
Giorgio