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.