2009-04-11 15 views
15

Sto usando __init__() in questo modo in alcune classi ORM di SQLAlchemy che hanno molti parametri (fino a 20).setattr con kwargs, pythonic o no?

def __init__(self, **kwargs): 
    for k, v in kwargs.iteritems(): 
     setattr(self, k, v) 

È "pythonic" impostare attributi come questo?

risposta

19

Sì. Un altro modo per farlo è.

def __init__(self, **kwargs): 
    self.__dict__.update(kwargs) 
+5

Questo è più corto rispetto alla versione nella domanda ma tenere presente che non funzionerà per gli attributi che sono proprietà (o altri descrittori). –

+0

Non consiglio di fare così. A volte incontrava qualche errore. quando si aggiorna l'attributo builtin '__dict__'. –

1

Per me sembra piuttosto pitonioso se ne hai solo bisogno in un posto nel tuo codice.

Il seguente link fornisce un approccio più 'generici' per lo stesso problema (ad esempio con un decoratore e alcune funzionalità extra), di dare un'occhiata a: http://code.activestate.com/recipes/551763/

4

Sì, se non c'è un modo "migliore" di fornire gli argomenti.

Ad esempio, utilizzando le classi ORM si parla, forse sarebbe più Python'y permettere ..

col = Varchar() 
col.index = True 
col.length = 255 

..rather di ..

col = Varchar(index = True, length = 255) 

Va bene che non è il miglior esempio, dal momento che il metodo **kwargs sarebbe effettivamente più bello .. ma il mio punto è che dovresti sempre considerare metodi alternativi per ottenere qualcosa, prima di usare cose a volte scoraggiate come **kwargs ..

Un'altra cosa da tenere a mente è che si potrebbe perdere il comportamento di un utente si aspetta, come l'aumento di un TypeError se l'utente fornisce un ARG parola chiave non valida, che potrebbe essere aggirato come ..

def __init__(self, **kwargs): 
    valid_kwargs = ['x', 'y', 'z'] 
    for k, v in kwargs.iteritems(): 
     if k not in valid_kwargs: 
      raise TypeError("Invalid keyword argument %s" % k) 
     setattr(self, k, v) 

Un ultima cosa da considerare:

class Hmm: 
    def __init__(self, **kwargs): 
     for k, v in kwargs.iteritems(): 
      setattr(self, k, v) 
    def mymethod(self): 
     print "mymethod should print this message.." 

x = Hmm(mymethod = None) 
x.mymethod() # raises TypeError: 'NoneType' object is not callable 
+0

E 'possibile cogliere il problema come quello che hai mostrato in classe 'Hmm'? Ad esempio, '__init__' controlla se un attributo è già presente e, in tal caso, genera un'eccezione anziché eseguire' setattr'? – max

+0

@max sì, il modo più semplice sarebbe fare 'if hasattr (self, k): ...' e lanciare un errore – dbr