PEP 3155 – Qualifizierter Name für Klassen und Funktionen
- Autor:
- Antoine Pitrou <solipsis at pitrou.net>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 29-Okt-2011
- Python-Version:
- 3.3
- Post-History:
- Resolution:
- Python-Dev Nachricht
Begründung
Pythons Introspektionsfunktionen hatten lange Zeit eine schlechte Unterstützung für verschachtelte Klassen. Aus einem Klassenobjekt ist es unmöglich zu erkennen, ob es innerhalb einer anderen Klasse oder auf Modul-Top-Level definiert wurde; und im ersteren Fall ist es auch unmöglich zu wissen, in welcher Klasse es definiert wurde. Während die Verwendung von verschachtelten Klassen oft als schlechter Stil gilt, ist der einzige Grund für ihre zweitrangige Introspektionsunterstützung ein lahmer Witz.
Python 3 fügt Salz auf die Wunde, indem es das verwirft, was früher als unbound methods bekannt war. In Python 2 können Sie bei der folgenden Definition
class C:
def f():
pass
sich vom C.f Objekt zu seiner definierenden Klasse hocharbeiten
>>> C.f.im_class
<class '__main__.C'>
Diese Möglichkeit ist in Python 3 nicht mehr gegeben
>>> C.f.im_class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'im_class'
>>> dir(C.f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__',
'__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__get__', '__getattribute__',
'__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__',
'__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__']
Dies schränkt die dem Benutzer zur Verfügung stehenden Introspektionsfähigkeiten weiter ein. Es kann tatsächliche Probleme beim Portieren von Software auf Python 3 verursachen, zum Beispiel Twisted Core, wo die Frage der Introspektion von Methodenobjekten mehrmals aufkam. Es schränkt auch die Pickle-Unterstützung ein [1].
Vorschlag
Dieser PEP schlägt die Hinzufügung eines Attributs __qualname__ zu Funktionen und Klassen vor. Für Top-Level-Funktionen und -Klassen ist das Attribut __qualname__ gleich dem Attribut __name__. Für verschachtelte Klassen, Methoden und verschachtelte Funktionen enthält das Attribut __qualname__ einen Punktpfad, der vom Modul-Top-Level zum Objekt führt. Der lokale Namensraum einer Funktion wird in diesem Punktpfad durch eine Komponente namens <locals> repräsentiert.
Die Darstellung von Funktionen und Klassen mit repr() und str() wird geändert, um __qualname__ anstelle von __name__ zu verwenden.
Beispiel mit verschachtelten Klassen
>>> class C:
... def f(): pass
... class D:
... def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'
Beispiel mit verschachtelten Funktionen
>>> def f():
... def g(): pass
... return g
...
>>> f.__qualname__
'f'
>>> f().__qualname__
'f.<locals>.g'
Einschränkungen
Bei verschachtelten Funktionen (und in Funktionen definierten Klassen) ist der Punktpfad nicht programmatisch begehbar, da der Namensraum einer Funktion von außen nicht zugänglich ist. Er wird für den menschlichen Leser immer noch hilfreicher sein als das bloße __name__.
Wie das Attribut __name__ wird das Attribut __qualname__ statisch berechnet und folgt nicht automatisch einer Neuzuweisung.
Diskussion
Ausschluss des Modulnamens
Wie __name__ beinhaltet __qualname__ nicht den Modulnamen. Dies macht es unabhängig von Modul-Aliasing und Neuzuweisungen und ermöglicht auch die Berechnung zur Kompilierzeit.
Wiederbelebung von unbound methods
Die Wiederbelebung von unbound methods würde nur einen Bruchteil der Probleme lösen, die dieser PEP löst, zu einem höheren Preis (ein zusätzlicher Objekttyp und eine zusätzliche Indirektion anstelle eines zusätzlichen Attributs).
Namenswahl
„Qualifizierter Name“ ist die beste Annäherung, als kurze Phrase, an das, worum es bei dem zusätzlichen Attribut geht. Es ist kein „vollständiger Name“ oder „fully qualified name“, da er (absichtlich) nicht den Modulnamen enthält. Ihn als „Pfad“ zu bezeichnen, würde die Verwechslungsgefahr mit Dateisystempfaden und dem Attribut __file__ bergen.
Der erste Vorschlag für den Attributnamen war, ihn __qname__ zu nennen, aber viele Leute (die nicht wissen, dass solche Fachbegriffe z.B. in der XML-Spezifikation verwendet werden [2]) fanden ihn obskur und nicht offensichtlich, weshalb der etwas weniger kurze und explizitere Name __qualname__ schließlich gewählt wurde.
Referenzen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-3155.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT