HOWTO · Python
Converti una stringa in nome variabile in Python
In questo articolo discuteremo vari modi per convertire un valore di stringa in un nome di variabile in Python.
In questa pagina
Python non usa il valore di una stringa come nome a sinistra di una normale assegnazione a una variabile. Per creare o accedere a un nome in fase di esecuzione, scegli lo spazio dei nomi che deve contenerlo: globals() per le variabili a livello di modulo, locals() per ispezionare i nomi locali, exec() per il codice sorgente generato, setattr() per gli attributi degli oggetti oppure un dizionario quando i nomi sono in realtà dati.
Nota: i nomi di variabile dinamici possono nascondere dipendenze, inquinare uno spazio dei nomi e generare un
NameErrorquando il codice legge un nome mai creato. Raramente sono la scelta migliore per il software di produzione; preferisci un dizionario, a meno che non sia davvero necessaria una variabile globale o un attributo di oggetto.
Convertire una stringa in un nome di variabile usando globals() e locals() in Python
La funzione incorporata globals() restituisce il dizionario della tabella dei simboli globale corrente. Questo dizionario associa il nome di ogni variabile globale al suo valore. Nell’ambito del modulo, scrivere una nuova chiave attraverso questo dizionario crea una vera variabile globale con quella stringa come nome.
Esegui questo esempio:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
def create_global_variable(name, value):
globals()[name] = value
variable_name = "dynamicGlobalVar"
variable_value = 10
create_global_variable(variable_name, variable_value)
print(dynamicGlobalVar)
10
La funzione riceve "dynamicGlobalVar" come argomento name e memorizza 10 sotto quella chiave nella tabella dei simboli globale. L’espressione successiva dynamicGlobalVar funziona perché il modulo ora ha una variabile globale con esattamente quel nome. La stringa deve essere un identificatore Python valido quando il codice sorgente deve accedervi per nome; altrimenti recupera il valore tramite globals()[name].
Un nome globale deve essere creato prima di essere letto. Se dynamicGlobalVar non fosse stato aggiunto prima alla tabella dei simboli globale, la riga finale genererebbe un NameError. Nel codice reale, preferisci una variabile come variable_name per la scrittura invece di inserire una stringa non verificata in tutto il programma.
Usare locals() per accedere a una variabile locale
La funzione locals() restituisce una mappatura che rappresenta la tabella dei simboli locale corrente. All’interno di una funzione, è utile per cercare un nome locale contenuto in una stringa:
def demonstrate_locals():
temp_var = "Dynamic Content"
name = "temp_var"
return locals().get(name)
print(demonstrate_locals())
Dynamic Content
Qui locals().get(name) risolve "temp_var" mentre la funzione è in esecuzione e restituisce il valore della variabile locale esistente. Usare .get() è più sicuro che indicizzare direttamente la mappatura perché restituisce None quando il nome richiesto è assente.
Non fare affidamento su locals()[name] = value per creare una variabile locale a una funzione. Le implementazioni di Python possono ottimizzare le variabili locali e le scritture sulla mappatura restituita non sono tenute ad aggiornare le associazioni locali reali dell’interprete. Tratta locals() principalmente come uno strumento di ricerca e ispezione; usa globals(), setattr() o un dizionario quando il programma ha bisogno di un nome dinamico scrivibile.
Convertire una stringa in un nome di variabile usando exec() in Python
La funzione exec() esegue codice sorgente Python fornito come stringa. Se quella stringa contiene un’assegnazione, eseguirla crea la variabile corrispondente nel contesto di esecuzione corrente.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
variable_name = "dynamicVar"
value = 42
exec(f"{variable_name} = {value}")
print(dynamicVar)
42
La f-string costruisce il testo sorgente dynamicVar = 42 ed exec() esegue quell’assegnazione. A livello di modulo, il risultato è una nuova variabile globale chiamata dynamicVar. Quando inserisci valori non numerici, usa repr() o una formattazione equivalente in modo che il sorgente generato contenga un letterale Python valido.
exec() è potente perché la stringa può contenere più di una singola assegnazione: può eseguire cicli, import, definizioni di funzioni o chiamate arbitrarie. Questa potenza è anche il suo pericolo principale. Non passare mai a exec() testo controllato dall’utente o comunque non affidabile; anche un nome o un frammento di valore malevolo può eseguire codice dannoso. Come locals(), anche exec() non è affidabile per aggiornare le variabili locali ottimizzate di una funzione, quindi questa tecnica è più chiara a livello di modulo o in un dizionario usato esplicitamente come spazio dei nomi.
Convertire una stringa in un nome di variabile usando setattr() in Python
Quando la “variabile” desiderata è in realtà un attributo di un oggetto, di una classe o di un modulo, setattr() è lo strumento più diretto. Accetta un oggetto, un nome di attributo sotto forma di stringa e il valore da assegnare.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
class Settings:
pass
settings = Settings()
attribute_name = "theme"
attribute_value = "dark"
setattr(settings, attribute_name, attribute_value)
print(settings.theme)
dark
La chiamata è equivalente a settings.theme = "dark", tranne che il nome dell’attributo proviene da attribute_name in fase di esecuzione. È utile per oggetti di configurazione, record, hook di plugin e altri punti in cui un oggetto usato come spazio dei nomi fa già parte della progettazione.
setattr() non crea una variabile ordinaria di modulo o di funzione; aggiorna lo spazio dei nomi degli attributi dell’oggetto di destinazione. Usa getattr(settings, attribute_name) per leggere il valore in modo dinamico oppure getattr(settings, attribute_name, default_value) quando serve un fallback.
Usare un dizionario al posto dei nomi di variabile dinamici in Python
Un dizionario è di solito la risposta più chiara quando un programma memorizza valori sotto nomi noti solo in fase di esecuzione. La stringa rimane una chiave, quindi l’insieme dei nomi dinamici resta esplicito e facile da ispezionare.
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
dynamic_vars = {}
var_name = "temperature"
var_value = 23
dynamic_vars[var_name] = var_value
print(dynamic_vars["temperature"])
23
Questo crea la stessa associazione di una variabile chiamata temperature che contiene 23, ma senza aggiungere nomi a uno spazio dei nomi Python. Le chiavi possono essere elencate, passate a un’altra funzione, serializzate o rimosse senza cercare in globals() voci impreviste.
Inoltre, le chiavi del dizionario non sono limitate dalle regole degli identificatori Python, quindi nomi come "daily total" possono essere usati come dati. Accedi a una chiave richiesta con dynamic_vars[var_name] oppure usa dynamic_vars.get(var_name) quando una chiave assente deve produrre un fallback invece di causare un errore. Questo evita la gestione di NameError, perché il programma sta interrogando una struttura dati anziché risolvere variabili a livello di codice sorgente.
Conclusione
Python offre diversi modi per trasformare una stringa ottenuta in fase di esecuzione in un nome utilizzabile. globals() può creare una vera variabile a livello di modulo attraverso la tabella dei simboli globale. locals() può cercare nomi locali, ma non è affidabile come meccanismo di scrittura. exec() può eseguire un’assegnazione generata, anche se comporta i maggiori rischi per la sicurezza e la chiarezza. setattr() è appropriato quando il nome dinamico appartiene a un oggetto o a un modulo.
Per la maggior parte dei programmi, un dizionario è la scelta più sicura e mantenibile. Mantiene i nomi dinamici sotto forma di dati, evita di inquinare gli spazi dei nomi Python e rende esplicito il comportamento in caso di nome mancante. Riserva variabili o attributi realmente dinamici ai casi in cui sono davvero necessari.