Einige aufrufbare Objekte zur Introspektion in Python
Introspektion wird in Python auch als „Inspektion“ bezeichnet. Damit ist gemeint, zur Laufzeit verschiedene Informationen über Objekte zu erhalten.
Objekte zur Introspektion sind also Objekte, mit denen man Informationen über andere Objekte erhalten kann.
Alle aufrufbaren Objekte dieser Lektion ergeben einen Wert (also ein Objekt) und bewirken keine Änderungen.
Vorimportierte Namen
Einige Namen aufrufbarer Objekte können ohne vorangehendes Importieren verwendet werden. Diese gehören entweder zur Programmiersprache selber oder zum Modul »builtins«, aus dem immer stillschweigend alle Attribute importiert sind.
»iskeyword«
Die Funktion »iskeyword« ergibt, ob eine Zeichenfolge ein Schlüsselwort ist.
- Protokoll
from keyword import iskeyword
iskeyword( 'lambda' )
True
- Auswertung
iskeyword( 'alpha' )
False
»type«
Die Klasse »type« kann ohne Import verwendet werden und ergibt den Typ eines Wertes, also eine Klasse.
Literale haben die schon früher für sie angegebenen Typen.
- Auswertung
type
<class 'type'>
- Auswertung
type( 9 )
<class 'int'>
- Auswertung
type( 9.2 )
<class 'float'>
- Auswertung
type( 'letters' )
<class 'str'>
- Auswertung
type( True )
<class 'bool'>
- Auswertung
type( None )
<class 'NoneType'>
- Auswertung
type( dir )
<class 'builtin_function_or_method'>
- Auswertung
type( lambda:9 )
<class 'function'>
- Auswertung
type( ( lambda:9 )() )
<class 'int'>
Mit Hilfe von »type« können wir nun auch sehen, daß »input« immer eine Zeichenfolge ergibt.
- Auswertung
type( input() )
abc
<class 'str'>
- Auswertung
type( input() )
123
<class 'str'>
- Auswertung
type( input() )
False
<class 'str'>
Mehr über »type« ⃗
»dir« ist ein aufrufbares Objekt. »builtin« bezieht sich in »builtin_function_or_method« nicht darauf, daß »dir« ohne Import verwendet werden kann, sondern darauf, daß »dir« nicht in Python, sondern in C geschrieben wurde.
- Auswertung
type( dir )
<class 'builtin_function_or_method'>
Der Wert eines Lambda-Ausdrucks ist eine Funktion.
- Auswertung
type( lambda: 2 )
<class 'function'>
Der Wert der Anwendung des Aufrufs der Funktion «lambda: 2» ist eine Zahl.
- Auswertung
type( ( lambda: 2 )() )
<class 'int'>
Die folgende Auswertung zeigt, daß »type« keine Funktion ist (es ist ein anderes aufrufbares Objekt).
- Auswertung
type( type )
<class 'type'>
Jeder Wert hat einen bestimmten Typ, auch das Ergebnis eines Aufrufs von »type«.
- Auswertung
type( type( type ))
<class 'type'>
Auch ein Klasse hat selber wieder eine Klasse als Typ!
- Auswertung
type( int )
<class 'type'>
Tatsächlich ist die Klasse »type« kein anderes Objekt als dasjenige Objekt, welches wir die ganze Zeit aufrufen!
- Auswertung
type( int )( float )
<class 'type'>
- Auswertung
type( int )( float )( str )
<class 'type'>
Mehr zum Umdefinieren von Standardnamen ⃗
Wenn der Bezeichner »float« an das Objekt ›int‹ gebunden wurde, dann ist »type( 1 )== float« wahr!
Definiert man anschließend noch »int = type( 1.1 )« hat man die Bedeutung von »int« und »float« genau vertauscht!
- Protokoll
type( 1 )== int
True
type( 1 )== float
False
float = int
type( 1 )== float
True
float
<class 'int'>
int = type( 1.1 )
type( 1 )==int
False
Vergleiche mit Klassen ⃗
Die meisten Namen von Klassen sind als Ausdrücke verwendbar, so daß Typen von Ausdrücken mit ihnen verglichen werden können.
- Auswertung
type( 2 )== int
True
- Eingabe eines Ausdrucks und Ausgabe einer Textdarstellung seines Wertes
type( 2 )
<class 'int'>
- Auswertung
int
<class 'int'>
Eine Ausnahme stellt jedoch der Name des Typs von ›None‹ dar, der nirgendwo (in keinem Standardmodul) definiert ist.
- Auswertung
type( None )
<class 'NoneType'>
- Protokoll
NoneType
NamensFehler: Der Name 'NoneType' ist nicht definiert.
Bei Bedarf könnte man den Namen »NoneType« jedoch selber definieren:
- Protokoll
NoneType = type( None )
type( None )== NoneType
True
Der Typ einer Klasse ist normalerweise das Objekt ›type‹.
- Auswertung
type( int )== type
True
Das Objekt ›type‹ ist gleichzeitig ein Objekt, ein aufrufbares Objekt (oben auf der linken Seite von »==«) und eine Klasse (oben auf der rechten Seite von »==« als Klasse des Objekts »int«).
»id« ⃗
Die Funktion »id« ergibt die sogenannte Identität ihres Argumentobjektes.
- Auswertung
id( id )
4428928
id( False )
8791421991280
id( True )
8791421991248
id( None )
8791422037216
id( "" )
4291808
id( 0 )
8791422522368
In Python hat jedes Objekt eine Identität. Es handelt sich dabei um eine ganze Zahl, welche sich zu einem bestimmten Zeitpunkt für jedes Objekt unterscheidet und so jedes Objekt eindeutig kennzeichnet. Während seiner gesamten Existenzdauer hat jedes Objekt immer die gleiche Identität. (Ein Objekt könnte aber dieselbe Identität haben wie ein anderes, früheres Objekt, das nicht mehr existiert.)
»isbuiltin« ⃗
Ein Prädikat ist ein aufrufbares Objekt, das einen Wahrheitswert ergibt.
Das Prädikat »isbuiltin« erlaubt es. eine Aussage zu schreiben, die besagt, daß das Argument eine „eingebaute“ Funktion ist.
- Protokoll
from inspect import isbuiltin
isbuiltin( type )
False
Der Begriff „eingebaut“ (“built-in ”) wird in Python allerdings in mehrdeutiger Weise verwendet:
- Bei einem Namen kann es bedeuten, daß er Teil des Moduls »builtins« ist.
- Bei einer Funktion kann es bedeuten, daß sie nicht in Python, sondern in der Programmiersprache C programmiert wurde.
- Bei einem Modul kann es bedeuten, daß das Modul ein fester Bestandteil der Python -Implementation ist, der nicht erst bei Bedarf von einem Massenspeicher gelesen werden muß, sondern sich schon beim Start der Python -Implementation im Hauptspeicher befindet. (Ein Import ist allerdings unter Umständen trotzdem noch zusätzlich nötig, um solch ein Modul nutzen zu können.)
Die beiden ersten Bedeutungen können bei einem Namen einer Funktion beziehungsweise der Funktion unabhängig voneinander zutreffen oder nicht zutreffen.
Welche Bedeutung gemeint ist, falls „eingebaut“ (“built-in ”) in einem Text verwendet wird, muß jeweils einzeln ermittelt werden.
In Falle des Prädikats »isbuiltin« ist die zweite Bedeutung gemeint. »isbuiltin( x )« bedeutet also, daß »x« in C geschrieben ist.
»isroutine« ⃗
Das Prädikat »isroutine« erlaubt es eine Aussage zu schreiben, die besagt, daß der Argumentwert eine Funktion ist.
- Protokoll
from inspect import isroutine
isroutine( type )
False
Tatsächlich ist »type« keine Funktion, wie wir ja schon weiter oben festgestellt hatten (es ist allerdings trotzdem wie eine Funktion aufrufbar!).
»isfunction« ⃗
Das Prädikat »isfunction« erlaubt es eine Aussage zu schreiben, die besagt, daß der Argumentwert eine in Python geschriebene Funktion ist.
- Protokoll
from inspect import isfunction
isfunction( type )
False
Tatsächlich ist »type« keine Funktion, wie wir ja schon weiter oben festgestellt hatten.
Dieses Prädikat ergibt aber auch dann ›False‹, wenn der Argumentwert zwar eine Funktion ist, diese aber nicht in Python geschrieben wurde.
Lambda-Funktionen sind in Python geschriebene Funktionen.
- Protokoll
from inspect import isfunction
isfunction( lambda: 2 )
True
»callable« ⃗
Das Prädikat »callable« erlaubt es zu schreiben, daß ein Wert aufrufbar ist, also daß er ein aufrufbares Objekt ist.
- Protokoll
callable( type )
True
Das Ergebnis bestätigt, daß »type« aufrufbar ist.
»getmodule« ⃗
Das aufrufbare Objekt »getmodule« versucht, das Modul zu ergeben, in dem ein Name definiert wurde.
- Protokoll
from inspect import getmodule
getmodule( type )
<module 'builtins' (built-in)>
Das Ergebnis bestätigt, daß »type« zum Modul »builtins« gehört. (Die Namen aus jenem Modul können ohne Import verwendet werden.)
»signature« ⃗
Die Funktion ›signature‹ ergibt die Signatur ihres Arguments. Dies geht aber bei einigen Python -Implementationen nicht für alle aufrufbaren Objekte.
- Protokoll (vereinfacht und frei übersetzt)
from inspect import signature
from operator import neg
signature( neg )
<Signature (a, /)>
signature( dir )
WertFehler: keine Signatur für die in C geschriebene Funktion "dir" gefunden
Die Signatur sollte die gleichen Informationen enthalten wie die Klammern in der Proklamation eines aufrufbaren Objektes, die man in seiner Dokumentation (z.B. mit »help«) findet, und zwar auch in der gleichen Schreibweise. In der Praxis weicht in der Dokumentation verwendete Schreibweise aber manchmal etwas ab.
Übungsfrage ⃗
? Übungsfrage ⃗
- Protokoll
type( help() )
Welcome to Python 3.6's help utility! …
Wo ist das Ergebnis von »type«?
Übungsaufgaben ⃗
/ Übungsaufgabe ⃗
Ermitteln Sie nach dem nötigen Import »from random import random« den Typ von »random« und »random()«, sowie die Werte von »isbuiltin«, »isroutine«, »isfunction«, »callable« und »getmodule«, wenn diese aufrufbaren Objekte auf »random« angewendet werden.