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

Python Enhancement Proposals

PEP 232 – Funktionsattribute

Autor:
Barry Warsaw <barry at python.org>
Status:
Final
Typ:
Standards Track
Erstellt:
02-Dez-2000
Python-Version:
2.1
Post-History:
20-Feb-2001

Inhaltsverzeichnis

Einleitung

Diese PEP beschreibt eine Erweiterung für Python, die Funktions- und Methodenobjekten Attribut-Dictionaries hinzufügt. Diese PEP verfolgt den Status und die Zuständigkeit für diese Funktion. Sie enthält eine Beschreibung der Funktion und skizziert die notwendigen Änderungen zur Unterstützung der Funktion. Diese PEP fasst Diskussionen in Mailinglistenforen zusammen und bietet, wo angemessen, URLs für weitere Informationen. Die CVS-Revisionshistorie dieser Datei enthält den definitiven historischen Bericht.

Hintergrund

Funktionen haben bereits eine Reihe von Attributen, von denen einige beschreibbar sind, z.B. func_doc, auch bekannt als func.__doc__. func_doc hat die interessante Eigenschaft, dass es in Funktions- (und Methoden-) Definitionen eine spezielle Syntax gibt, um das Attribut implizit zu setzen. Dieser Komfort wurde immer wieder ausgenutzt, wobei Docstrings mit zusätzlicher Semantik überladen wurden.

Zum Beispiel hat John Aycock ein System geschrieben, in dem Docstrings zur Definition von Parsing-Regeln verwendet werden. [1] Zopes ZPublisher ORB [2] verwendet Docstrings, um veröffentlichte Methoden zu kennzeichnen, d.h. Methoden, die über das Web aufgerufen werden können.

Das Problem bei diesem Ansatz ist, dass die überladene Semantik miteinander in Konflikt geraten kann. Zum Beispiel, wenn wir einen Doctest für eine Zope-Methode hinzufügen wollten, die nicht über das Web veröffentlicht werden soll.

Vorschlag

Dieser Vorschlag fügt Funktions-Objekten ein neues Dictionary namens func_dict (auch bekannt als __dict__) hinzu. Dieses Dictionary kann mit der üblichen Attribut-Setz- und Abruf-Syntax gesetzt und abgerufen werden.

Methoden erhalten ebenfalls Getter-Syntax und greifen derzeit über das Dictionary des zugrunde liegenden Funktions-Objekts auf das Attribut zu. Es ist nicht möglich, Attribute auf gebundenen oder ungebundenen Methoden zu setzen, außer indem dies explizit auf dem zugrunde liegenden Funktions-Objekt geschieht. Siehe die Diskussion Zukünftige Richtungen unten für Ansätze in nachfolgenden Python-Versionen.

Das __dict__ eines Funktions-Objekts kann ebenfalls gesetzt werden, aber nur auf ein Dictionary-Objekt. Das Löschen des __dict__ einer Funktion oder das Setzen auf etwas anderes als ein konkretes Dictionary-Objekt führt zu einem TypeError. Wenn bisher keine Funktionsattribute gesetzt wurden, ist das __dict__ der Funktion leer.

Beispiele

Hier sind einige Beispiele, was Sie mit dieser Funktion tun können.

def a():
    pass

a.publish = 1
a.unittest = '''...'''

if a.publish:
    print a()

if hasattr(a, 'unittest'):
    testframework.execute(a.unittest)

class C:
    def a(self):
        'just a docstring'
        a.publish = 1

c = C()
if c.a.publish:
    publish(c.a())

Andere Verwendungen

Paul Prescod zählte auf dem python-dev Thread eine Reihe weiterer Verwendungen auf.

Zukünftige Richtungen

Hier sind eine Reihe von zukünftigen Richtungen, die in Betracht gezogen werden sollten. Jede Übernahme dieser Ideen würde eine neue PEP erfordern, die sich auf diese bezieht und für eine Python-Version nach der 2.1-Veröffentlichung gezielt wäre.

  • Eine frühere Version dieser PEP erlaubte sowohl Setzen als auch Abrufen von Attributen auf ungebundenen Methoden und nur Abrufen auf gebundenen Methoden. Eine Reihe von Problemen wurde mit dieser Richtlinie entdeckt.

    Da Methodenattribute im zugrunde liegenden Funktionsobjekt gespeichert wurden, führte dies zu mehreren potenziell überraschenden Ergebnissen

    class C:
        def a(self): pass
    
    c1 = C()
    c2 = C()
    c1.a.publish = 1
    # c2.a.publish would now be == 1 also!
    

    Da eine Änderung an a gebundener c1 auch eine Änderung an a gebunden an c2 verursachte, wurde das Setzen von Attributen auf gebundenen Methoden verboten. Selbst das Zulassen des Setzens von Attributen auf ungebundenen Methoden birgt jedoch Mehrdeutigkeiten

    class D(C): pass
    class E(C): pass
    
    D.a.publish = 1
    # E.a.publish would now be == 1 also!
    

    Aus diesem Grund verbietet die aktuelle PEP das Setzen von Attributen auf gebundenen oder ungebundenen Methoden, erlaubt jedoch das Abrufen von Attributen auf beiden – beide geben den Attributwert des zugrunde liegenden Funktions-Objekts zurück.

    Eine zukünftige PEP könnte vorschlagen, das Setzen von (gebundenen oder ungebundenen) Methodenattributen zu implementieren, indem Attribute auf der Instanz oder der Klasse gesetzt werden, unter Verwendung spezieller Namenskonventionen. D.h.

    class C:
        def a(self): pass
    
    C.a.publish = 1
    C.__a_publish__ == 1 # true
    
    c = C()
    c.a.publish = 2
    c.__a_publish__ == 2 # true
    
    d = C()
    d.__a_publish__ == 1 # true
    

    Hier würde eine Suche auf der Instanz zuerst im Dictionary der Instanz suchen, gefolgt von einer Suche im Dictionary der Klasse und schließlich einer Suche im Dictionary des Funktions-Objekts.

  • Derzeit unterstützt Python Funktionsattribute nur für Python-Funktionen (d.h. für solche, die in Python geschrieben sind, nicht für eingebaute). Wenn es sich lohnt, kann ein separater Patch erstellt werden, der Funktionsattribute zu eingebauten Funktionen hinzufügt.
  • __doc__ ist das einzige Funktionsattribut, das derzeit syntaktische Unterstützung für das bequeme Setzen hat. Es könnte sich lohnen, die Sprache schließlich für die Unterstützung des einfachen Setzens von Funktionsattributen zu erweitern. Hier sind einige von PEP-Rezensenten vorgeschlagene Syntaxen: [3]
    def a {
        'publish' : 1,
        'unittest': '''...''',
        }
        (args):
        # ...
    
    def a(args):
        """The usual docstring."""
        {'publish' : 1,
         'unittest': '''...''',
         # etc.
         }
    
    def a(args) having (publish = 1):
        # see reference [3]
        pass
    

    Der BDFL ist derzeit gegen jede solche spezielle syntaktische Unterstützung für das Setzen willkürlicher Funktionsattribute. Jegliche Syntaxvorschläge müssten in neuen PEPs dargelegt werden.

Abweichende Meinung

Als dies im April 2000 auf der python-dev Mailingliste diskutiert wurde, wurden eine Reihe von abweichenden Meinungen geäußert. Zur Vollständigkeit beginnt der Diskussionsfaden auf python-dev.

Die abweichenden Argumente scheinen unter die folgenden Kategorien zu fallen

  • kein klarer Zweck (was bringt es einem?)
  • andere Wege, dies zu tun (z.B. Mappings als Klassenattribute)
  • nutzlos, bis syntaktische Unterstützung enthalten ist

Als Gegenargument zu einigen dieser Argumente ist die Beobachtung, dass mit Vanilla Python 2.0 __doc__ tatsächlich auf jeden Objekttyp gesetzt werden kann, sodass eine gewisse Ähnlichkeit von beschreibbaren Funktionsattributen bereits machbar ist. Aber dieser Ansatz ist eine weitere Korruption von __doc__.

Und obwohl es natürlich möglich ist, Mappings zu Klassenobjekten hinzuzufügen (oder im Falle von Funktionsattributen zum Modul der Funktion), ist es schwieriger und weniger offensichtlich, wie die Attributwerte zur Inspektion extrahiert werden können.

Schließlich kann es wünschenswert sein, syntaktische Unterstützung hinzuzufügen, ähnlich wie die __doc__ syntaktische Unterstützung existiert. Dies kann separat von der Fähigkeit, Funktionsattribute tatsächlich zu setzen und abzurufen, betrachtet werden.

Referenzimplementierung

Diese PEP wurde angenommen und die Implementierung wurde in Python 2.1 integriert.

Referenzen


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

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