Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 312 – Einfaches implizites Lambda

Autor:
Roman Suzi <rnd at onego.ru>, Alex Martelli <aleaxit at gmail.com>
Status:
Verschoben
Typ:
Standards Track
Erstellt:
11. Feb. 2003
Python-Version:
2.4
Post-History:


Inhaltsverzeichnis

Zusammenfassung

Dieser PEP schlägt vor, das schlüsselwortlose Lambda-Schlüsselwort in Fällen optional zu machen, in denen es grammatikalisch nicht mehrdeutig ist.

Zurückgestellt

Der BDFL hasst die Unary-Colon-Syntax. Dieser PEP muss noch einmal überarbeitet werden, um eine Pythonischere Syntax zu finden (vielleicht einen alternativen Unary-Operator). Siehe Diskussion auf python-dev vom 17. Juni 2005 [1].

Es ist wahrscheinlich auch eine gute Idee, die alternativen Vorschläge, die keine Chance haben, zu eliminieren. Der Abschnitt Beispiele ist gut und hebt die Verbesserungen der Lesbarkeit hervor. Er würde mit zusätzlichen Beispielen und realen Referenzen (anstatt der abstrahierten Dummy-Aufrufe von :A und :B) mehr Gewicht tragen.

Motivation

Lambdas sind nützlich für die Definition anonymer Funktionen, z. B. als Callbacks oder (Pseudo)-Lazy-Evaluation-Schemata. Oft werden Lambdas nicht verwendet, obwohl sie angebracht wären, nur weil das Schlüsselwort "lambda" den Code komplex erscheinen lässt. Das Auslassen von Lambda in einigen Sonderfällen ist möglich, mit kleinen und rückwärtskompatiblen Änderungen an der Grammatik und bietet eine günstige Lösung gegen solche "Lambdaphobie".

Begründung

Manchmal verwenden Leute keine Lambdas, weil sie Angst haben, einen Begriff mit einer dahinterstehenden Theorie einzuführen. Dieser Vorschlag erleichtert die Einführung von schlüsselwortlosen Lambdas, indem das "lambda"-Schlüsselwort selbst weggelassen wird. Die Implementierung kann einfach durch Änderung der Grammatik erfolgen, sodass das "lambda"-Schlüsselwort in einigen wenigen bekannten Fällen impliziert wird. Insbesondere das Hinzufügen von umschließenden Klammern ermöglicht es, Nullary-Lambdas überall anzugeben.

Syntax

Ein schlüsselwortloses "lambda"-Schlüsselwort kann in folgenden Fällen weggelassen werden

  • unmittelbar nach "=" in der Benennung von Parameterzuweisungen oder Standardwertzuweisungen;
  • unmittelbar nach "(" in jedem Ausdruck;
  • unmittelbar nach "," in einer Funktionsargumentliste;
  • unmittelbar nach ":" in einem Dictionary-Literal; (nicht implementiert)
  • in einer Zuweisungsanweisung; (nicht implementiert)

Anwendungsbeispiele

  1. Inline if
    def ifelse(cond, true_part, false_part):
        if cond:
            return true_part()
        else:
            return false_part()
    
    # old syntax:
    print ifelse(a < b, lambda:A, lambda:B)
    
    # new syntax:
    print ifelse(a < b, :A, :B)
    
    # parts A and B may require extensive processing, as in:
    print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
    
  2. Sperren
    def with(alock, acallable):
        alock.acquire()
        try:
            acallable()
        finally:
            alock.release()
    
    with(mylock, :x(y(), 23, z(), 'foo'))
    

Implementierung

Die Implementierung erfordert einige Anpassungen der Datei Grammar/Grammar in den Python-Quellen und einige Anpassungen von Modules/parsermodule.c, um syntaktische und pragmatische Änderungen vorzunehmen.

(Ein Guru für Grammatik/Parser wird benötigt, um eine vollständige Implementierung vorzunehmen.)

Hier sind die Änderungen, die an Grammar vorgenommen werden müssen, um implizites Lambda zu ermöglichen

varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
imptest])* [',']

imptest: test | implambdef

atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+

implambdef: ':' test

imptestlist: imptest (',' imptest)* [',']

argument: [test '='] imptest

Drei neue Nichtterminale werden benötigt: imptest für den Ort, an dem implizites Lambda auftreten kann, implambdef für die implizite Lambda-Definition selbst, imptestlist für einen Ort, an dem imptest's auftreten können.

Diese Implementierung ist nicht vollständig. Erstens, weil einige Dateien im Parser-Modul aktualisiert werden müssen. Zweitens sind einige zusätzliche Stellen nicht implementiert, siehe Syntax-Abschnitt oben.

Diskussion

Dieses Feature ist kein Feature mit hoher Sichtbarkeit (der einzige neuartige Teil ist die Abwesenheit von lambda). Das Feature soll nullary Lambdas syntaktisch attraktiver machen und die Lazy Evaluation von Ausdrücken in einigen einfachen Fällen ermöglichen. Dieser Vorschlag richtet sich nicht an fortgeschrittenere Fälle (die Argumente für das Lambda erfordern).

Es gibt einen alternativen Vorschlag für implizites Lambda: implizites Lambda mit unbenutzten Argumenten. In diesem Fall kann die von einem solchen Lambda definierte Funktion beliebige Parameter akzeptieren, d. h. äquivalent sein zu: lambda *args: expr. Diese Form wäre leistungsfähiger. Eine Suche in der Standardbibliothek ergab, dass solche Lambdas tatsächlich verwendet werden.

Eine weitere Erweiterung könnte eine Möglichkeit bieten, eine Liste von Parametern an eine Funktion zu übergeben, die durch implizites Lambda definiert ist. Solche Parameter benötigen jedoch einen speziellen Namen, um darauf zugreifen zu können, und werden wahrscheinlich nicht in die Sprache aufgenommen. Mögliche lokale Namen für solche Parameter sind: _, __args__, __. Zum Beispiel

reduce(:_[0] + _[1], [1,2,3], 0)
reduce(:__[0] + __[1], [1,2,3], 0)
reduce(:__args__[0] + __args__[1], [1,2,3], 0)

Diese Formen sehen nicht sehr schön aus und rechtfertigen nach Ansicht des PEP-Autors nicht die Entfernung des lambda-Schlüsselworts in diesen Fällen.

Danksagungen

Die Idee, lambda zu verwerfen, wurde zuerst von Paul Rubin am 08. Feb. 2003 um 16:39:30 -0800 in comp.lang.python im Rahmen der Diskussion des Threads "For review: PEP 308 - If-then-else expression" [2] geprägt.

Referenzen


Quelle: https://github.com/python/peps/blob/main/peps/pep-0312.rst

Zuletzt geändert: 2025-02-01 08:59:27 GMT