3.4. Ottenere riferimenti agli oggetti usando getattr

Già sapete che le funzioni in Python sono oggetti. Quello che non sapete è che potete ottenere un riferimento da una funzione senza conoscere il suo nome fino al momento dell'esecuzione, utilizzando la funzione getattr.

Esempio 3.11. Introduzione a getattr

>>> li = ["Larry", "Curly"]
>>> li.pop                       1
<built-in method pop of list object at 010DF884>
>>> getattr(li, "pop")           2
<built-in method pop of list object at 010DF884>
>>> getattr(li, "append")("Moe") 3
>>> li
["Larry", "Curly", "Moe"]
>>> getattr({}, "clear")         4
<built-in method clear of dictionary object at 00F113D4>
>>> getattr((), "pop")           5
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'pop'
1 Così si ottiene un riferimento al metodo pop della lista. Notate che questo non significa chiamare il metodo pop; per farlo bisogna scrivere li.pop(). Questo è proprio il metodo.
2 Anche in questo modo si ottiene un riferimento al metodo pop, ma questa volta il nome del metodo è specificato come argomento di tipo stringa per la funzione getattr. getattr è una funzione built-in incredibilmente utile, che ritorna ogni attributo di ogni oggetto. in questo caso, l'oggetto è una lista e l'attributo è il metodo pop.
3 Nel caso non abbiate ancora bene afferrato quanto sia utile, provate questo: il valore di ritorno di getattr è un metodo, che potete chiamare proprio come se scriveste li.append("Moe") direttamente. Ma non avete chiamato la funzione direttamente; avete invece specificato il nome della funzione.
4 getattr funziona anche sui dizionari.
5 In teoria getattr funzionerebbe anche sulle tuple, eccetto per il fatto che le tuple non hanno metodi, così getattr genererà un'eccezione a prescindere da quale nome di attributo le passiate.

getattr non è fatta solamente per i tipi di dato built-in. Funziona anche con i moduli.

Esempio 3.12. getattr in apihelper.py

>>> import odbchelper
>>> odbchelper.buildConnectionString             1
<function buildConnectionString at 00D18DD4>
>>> getattr(odbchelper, "buildConnectionString") 2
<function buildConnectionString at 00D18DD4>
>>> object = odbchelper
>>> method = "buildConnectionString"
>>> getattr(object, method)                      3
<function buildConnectionString at 00D18DD4>
>>> type(getattr(object, method))                4
<type 'function'>
>>> import types
>>> type(getattr(object, method)) == types.FunctionType
1
>>> callable(getattr(object, method))            5
1
1 Così si ottiene un riferimento alla funzione buildConnectionString nel modulo odbchelper che abbiamo studiato nella sezione Conoscere Python. (L'indirizzo esadecimale che vedete è specifico della mia macchina, il vostro output sarà diverso.)
2 Usando getattr possiamo ottenere lo stesso riferimento alla stessa funzione. In generale, getattr(oggetto, "attributo") è equivalente a oggetto.attributo. Se oggetto è un modulo, allora attributo può essere qualunque cosa definita nel modulo: una funzione, una classe o una variabile globale.
3 E questo è ciò che usiamo nella funzione help. oggetto è passato alla funzione come argomento, method è una stringa che rappresenta il nome di un metodo o di una funzione.
4 In questo caso, method è il nome di una funzione e lo possiamo dimostrare ottenendone il type.
5 Siccome method è una funzione, allora è invocabile.