2.33. Introspektion¶
Eine Handvoll eingebauter Funktionen erlauben es einem laufenden Programm, sich selbst zu untersuchen – die Werte, mit denen es arbeitet, die Namensräume, in denen diese Werte leben, und die Beziehungen zwischen Klassen. Greifen Sie darauf zurück, wenn Sie Entscheidungen darauf stützen müssen, was ein Objekt tatsächlich ist, statt darauf, was sein Aufrufer behauptet.
2.33.1. Identität und Hashing¶
id()– eine eindeutige Ganzzahl, die ein Objekt identifiziert, solange es lebt. Zwei Namen, die dasselbe Objekt binden, liefern dieselbe id zurück; zwei gleiche, aber verschiedene Objekte tun das nicht.
>>> a = [1, 2, 3]
>>> b = a
>>> c = [1, 2, 3]
>>> id(a) == id(b) # same list
True
>>> id(a) == id(c) # equal but distinct
False
Die id ist nicht über Programmläufe hinweg portierbar und über „dasselbe Objekt oder ein anderes Objekt“ hinaus nicht aussagekräftig.
hash()– der Hash-Wert eines Objekts, dieselbe Zahl, diedictundsetzum Nachschlagen verwenden. Zwei gleiche Objekte hashen zum selben Wert; nur hashbare Typen (meist unveränderliche Werte) funktionieren überhaupt.
>>> hash("abc") # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'
2.33.2. Typen und Aufrufbarkeit abfragen¶
type()– die exakte Klasse eines Werts.type(x) is intfragt „ist x exakt ein int“ (keine Unterklassen);isinstance()ist normalerweise das, was Sie stattdessen wollen.isinstance()– „ist x eine Instanz dieser Klasse oder einer Unterklasse davon?“ Das Standardwerkzeug für typbasierte Verteilung innerhalb von Funktionen.issubclass()– das Gegenstück auf Klassenebene. Nimmt zwei Klassen statt einer Instanz.callable()–True, wenn das Argument mit()aufgerufen werden kann. Nützlich, wenn Sie ein Argument erhalten, das eine Funktion oder ein einfacher Wert sein kann.
>>> isinstance(3, int)
True
>>> isinstance(True, int) # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False
Ein Muster, das callable verwendet:
def call_or_return(x):
return x() if callable(x) else x
2.33.3. Geltungsbereiche betrachten¶
globals()– der globale Namensraum des Moduls alsdict. Das Lesen daraus funktioniert; das Schreiben hinein ist echt, aber dies außerhalb der REPL-Erkundung zu tun macht ein Programm schwer nachvollziehbar.locals()– der lokale Namensraum an der Aufrufstelle. Innerhalb einer Funktion spiegelt er die lokalen Variablen wider; das Verändern des zurückgegebenen Dicts schreibt nicht garantiert in die tatsächlichen Locals zurück (implementierungsabhängiges Verhalten).
name = "OpenMV"
def f():
x = 10
print(globals()["name"]) # OpenMV
print(locals()) # {'x': 10}
Diese beiden sind nützlich zum Debuggen und für Werkzeuge, die herausfinden müssen, was definiert ist. Greifen Sie in regulärem Code sparsam darauf zurück – eine Funktion, die globals() verändert, gehört zu den am schwersten nachvollziehbaren Dingen in Python.
2.33.4. Siehe auch¶
dir() und help(), behandelt in debugging, sind die alltäglichen Introspektionswerkzeuge zum Erkunden der Oberfläche eines unbekannten Objekts.