Vale la pena notare che per il problema specifico in questione, ci sono diverse alternative all'utilizzo eval
:
Il più semplice, come notato, sta usando setattr
:
def __init__(self):
for name in attsToStore:
setattr(self, name, None)
Un approccio meno ovvio è l'aggiornamento __dict__
diretto dell'oggetto dell'oggetto. Se tutto ciò che vuoi fare è inizializzare gli attributi None
, allora questo è meno semplice di quanto sopra. Ma considera questo:
def __init__(self, **kwargs):
for name in self.attsToStore:
self.__dict__[name] = kwargs.get(name, None)
Ciò consente di passare argomenti di parole chiave al costruttore, ad esempio:
s = Song(name='History', artist='The Verve')
Ti consente anche di rendere il tuo uso locals()
più esplicito, ad esempio:
s = Song(**locals())
... e, se vuoi davvero assegnarlo None
agli attributi i cui nomi si trovano in locals()
:
s = Song(**dict([(k, None) for k in locals().keys()]))
Un altro approccio per fornire un oggetto con valori predefiniti per un elenco di attributi è quello di definire la classe __getattr__
metodo :
def __getattr__(self, name):
if name in self.attsToStore:
return None
raise NameError, name
Questo metodo viene chiamato quando l'attributo denominato non viene trovato nel modo normale. Questo approccio è un po 'meno semplice rispetto alla semplice impostazione degli attributi nel costruttore o all'aggiornamento di__dict__
, ma ha il merito di non creare effettivamente l'attributo a meno che non esista, il che può ridurre sostanzialmente l'utilizzo della memoria della classe.
Il punto di tutto ciò: ci sono molte ragioni, in generale, da evitare eval
: il problema di sicurezza dell'esecuzione del codice che non si controlla, il problema pratico del codice che non è possibile eseguire il debug, ecc. Ma una ragione ancora più importante è che in genere non è necessario utilizzarlo. Python espone così tanto dei suoi meccanismi interni al programmatore che raramente hai davvero bisogno di scrivere codice che scriva codice.
exec/eval
saputo e ancora non lo sapevisetattr
?