2.33. Introspektion¶
En handfull inbyggda funktioner låter ett körande program inspektera sig självt – värdena det arbetar med, namnrymderna som dessa värden lever i, och relationerna mellan klasser. Ta till dem när du behöver fatta beslut baserat på vad ett objekt faktiskt är, snarare än vad dess anropare påstår att det är.
2.33.1. Identitet och hashning¶
id()– ett unikt heltal som identifierar ett objekt så länge det lever. Två namn som binder samma objekt returnerar samma id; två lika men distinkta objekt gör det inte.
>>> 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
Detta id är inte portabelt mellan körningar och inte meningsfullt utöver ”samma objekt eller annat objekt.”
hash()– hashvärdet för ett objekt, samma tal somdictochsetanvänder för att slå upp det. Två lika objekt hashar till samma värde; endast hashbara typer (oföränderliga värden, mestadels) fungerar över huvud taget.
>>> hash("abc") # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'
2.33.2. Fråga efter typer och anropbarhet¶
type()– den exakta klassen för ett värde.type(x) is intfrågar ”är x exakt en int” (inga underklasser);isinstance()är vanligtvis det du vill ha i stället.isinstance()– ”är x en instans av denna klass, eller en underklass till den?” Standardverktyget för typbaserad sändning inuti funktioner.issubclass()– motsvarigheten på klassnivå. Tar två klasser snarare än en instans.callable()–Trueom argumentet kan anropas med(). Användbart när du tar emot ett argument som kan vara en funktion eller kan vara ett enkelt värde.
>>> isinstance(3, int)
True
>>> isinstance(True, int) # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False
Ett mönster som använder callable:
def call_or_return(x):
return x() if callable(x) else x
2.33.3. Titta på omfång¶
globals()– modulens globala namnrymd som endict. Att läsa från den fungerar; att skriva till den är reellt, men att göra det utanför REPL-utforskning gör ett program svårt att följa.locals()– den lokala namnrymden vid anropsstället. Inuti en funktion återspeglar den de lokala variablerna; att modifiera den returnerade ordboken är inte garanterat att skriva tillbaka in i de faktiska lokala variablerna (implementationsdefinierat beteende).
name = "OpenMV"
def f():
x = 10
print(globals()["name"]) # OpenMV
print(locals()) # {'x': 10}
Dessa två är användbara för felsökning och för verktyg som behöver upptäcka vad som är definierat. Ta till dem sparsamt i vanlig kod – en funktion som muterar globals() är en av de svåraste sakerna att resonera kring i Python.
2.33.4. Se även¶
dir() och help(), som täcks i debugging, är de vardagliga introspektionsverktygen för att utforska ytan av ett okänt objekt.