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

Python Enhancement Proposals

PEP 542 – Punktnotation-Zuweisung in Funktionsheadern

Autor:
Markus Meskanen <markusmeskanen at gmail.com>
Status:
Abgelehnt
Typ:
Standards Track
Erstellt:
10-Feb-2017
Resolution:
Python-Dev Nachricht

Inhaltsverzeichnis

Zusammenfassung

Funktionsdefinitionen erlauben nur die Verwendung einfacher Funktionsnamen, obwohl Funktionen als zuweisbare First-Class-Objekte gelten.

Dieses PEP schlägt die Unterstützung für die Zuweisung einer Funktion zu einem Klassen- oder Instanzattribut direkt im Header der Funktionsdefinition vor, indem die Punktnotation verwendet wird, um das Objekt vom Namen der Funktion zu trennen.

Obwohl dies eine ähnliche Funktion ist, befasst sich dieses PEP nicht mit der allgemeinen Zuweisung an alles, was Zuweisung unterstützt, wie z. B. Wörterbuchschlüssel und Listenindizes.

Begründung

Derzeit erfordert es eine zusätzliche Zuweisungsanweisung, wenn eine Funktion einem Klassen- oder Instanzattribut zugewiesen werden muss.

class MyClass:
    ...

my_instance = MyClass()

def my_function(self):
    ...

# Assign to class attribute
MyClass.my_function = my_function

# Or assign to instance attribute
my_instance.my_function = my_function

Obwohl dies normalerweise keine Unannehmlichkeit darstellt, würde die Verwendung der Punktnotation zur direkten Zuweisung im Header der Funktion dies erheblich vereinfachen.

class MyClass:
    ...

my_instance = MyClass()

# Assign to class attribute
def MyClass.my_function(self):
    ...

# Or assign to instance attribute
def my_instance.my_function(self):
    ...

Es gibt mehrere Gründe, diese Funktionalität gegenüber einer Standard-Klassenmethode zu verwenden, zum Beispiel wenn die Klasse innerhalb des Headers der Funktion referenziert wird (wie bei Dekoratoren und Typisierung). Dies ist auch nützlich, wenn eine Instanz ein Callback-Attribut benötigt.

class Menu:
    def __init__(self, items=None, select_callback=None):
        self.items = items if items is not None else []
        self.select_callback = select_callback

my_menu = Menu([item1, item2])

def my_menu.select_callback(item_index, menu):
    print(menu.items[item_index])

Im Gegensatz zu

my_menu = Menu([item1, item2])

def select_callback(item_index, menu):
    print(menu.items[item_index])
my_menu.select_callback = select_callback

Oder sie in einer „unnatürlichen“ Reihenfolge definieren

def select_callback(item_index, menu):
    print(menu.items[item_index])

my_menu = Menu([item1, item2], select_callback)

Es liest sich besser als die „unnatürliche“ Art, da man zum Zeitpunkt der Funktionsdefinition bereits weiß, wofür sie verwendet werden soll. Es spart auch eine Codezeile und reduziert die visuelle Komplexität.

Die Funktion würde auch vermeiden, den Namen der Funktion im globalen Namensraum zu belassen.

eggs = 'something'

def Spam.eggs(self):
    ...

def Cheese.eggs(self):
    ...

assert eggs == 'something'

Idealerweise wäre dies nur syntaktischer Zucker

def x.y():
    ...

# Equals to

def y():
    ...
x.y = y

Ähnlich wie Dekoratoren syntaktischer Zucker sind.

@decorate
def f():
    ...

# Equals to

def f():
    ...
f = decorate(f)

Implementierung

Die __name__ würde den Prinzipien einer normalen Funktion folgen.

class MyClass:
    def my_function1(self):
        ...

def MyClass.my_function2(self):
    ...

assert my_function1.__name__ == 'my_function1'
assert my_function2.__name__ == 'my_function2'

Die Grammatik würde dotted_name verwenden, um die Verkettung von Attributen zu unterstützen.

def Person.name.fset(self, value):
    self._name = value

Abwärtskompatibilität

Dieser PEP ist vollständig abwärtskompatibel.


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

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