2.33. Introspecție

Câteva funcții încorporate permit unui program în execuție să se inspecteze pe sine – valorile cu care lucrează, spațiile de nume în care trăiesc acele valori și relațiile dintre clase. Apelează la ele când trebuie să iei decizii pe baza a ceea ce un obiect este de fapt, mai degrabă decât a ceea ce pretinde apelantul său.

2.33.1. Identitate și hashing

  • id() – un întreg unic care identifică un obiect atât timp cât acesta este activ. Două nume care leagă același obiect întorc același id; două obiecte egale, dar distincte, nu.

>>> 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

Id-ul nu este portabil între rulări și nu are sens dincolo de „același obiect sau un obiect diferit.”

  • hash() – valoarea hash a unui obiect, același număr pe care dict și set îl folosesc pentru a-l căuta. Două obiecte egale au aceeași valoare hash; doar tipurile hashabile (valori imutabile, în general) funcționează în general.

>>> hash("abc")           # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'

2.33.2. Interogarea tipurilor și a posibilității de apelare

  • type() – clasa exactă a unei valori. type(x) is int întreabă „este x exact un int” (fără subclase); isinstance() este de obicei ceea ce vrei în schimb.

  • isinstance() – „este x o instanță a acestei clase sau a unei subclase a ei?” Instrumentul standard pentru distribuirea bazată pe tip în interiorul funcțiilor.

  • issubclass() – echivalentul la nivel de clasă. Primește două clase în loc de o instanță.

  • callable()True dacă argumentul poate fi apelat cu (). Util când primești un argument care poate fi o funcție sau poate fi o valoare simplă.

>>> isinstance(3, int)
True
>>> isinstance(True, int)        # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False

Un model care folosește callable:

def call_or_return(x):
    return x() if callable(x) else x

2.33.3. Examinarea domeniilor

  • globals() – spațiul de nume global al modulului ca dict. Citirea din el funcționează; scrierea în el este reală, dar a face acest lucru în afara explorării REPL face un program greu de urmărit.

  • locals() – spațiul de nume local de la locul apelului. În interiorul unei funcții reflectă variabilele locale; modificarea dicționarului întors nu garantează scrierea înapoi în variabilele locale reale (comportament definit de implementare).

name = "OpenMV"

def f():
    x = 10
    print(globals()["name"])    # OpenMV
    print(locals())             # {'x': 10}

Acestea două sunt utile pentru depanare și pentru instrumente care trebuie să descopere ce este definit. Apelează la ele cu moderație în codul obișnuit – o funcție care modifică globals() este unul dintre cele mai greu de înțeles lucruri din Python.

2.33.4. Vezi și

dir() și help(), tratate în debugging, sunt instrumentele de introspecție de zi cu zi pentru explorarea suprafeței unui obiect necunoscut.