2010-02-15 13 views
8

stavo cercando di generare una classe da un dizionario:classe aggiunta di attributi utilizzando un ciclo for in Python

class attr: 
    for key in objects_type: 
     setattr(attr, key, lambda cl: list()) 

Questo dà l'errore che attr non è definito durante il ciclo for. So che potrei scrivere:

class attr: 
    pass 
for key in objects_type: 
    setattr(attr, key, lambda cl: list()) 

Ma sono sicuro che ricordo di aver visto codice simile al primo esempio da qualche parte. Qualcuno sa se è possibile scrivere qualcosa di simile al primo modulo?

risposta

6

Anche se non è molto elegante, è possibile utilizzare locals():

>>> class c(object): 
...  for i in range(10): 
...   locals()['A' + str(i)] = i 
... 
>>> c.A0 
0 
>>> c.A7 
7 
+0

Deve essere stato quello che ricordo di aver visto. Grazie – Casebash

+0

In effetti, penso che sia più bello dell'uso di setattr - quindi non direi che è inelegante – Casebash

+6

Non si dovrebbe cambiare la dicitura locale(): http://docs.python.org/library/functions .html # locals – stephan

2

Non so esattamente cosa stai facendo. Posso darvi esempio di aggiungere attributi di classe a una classe in un ciclo for:

attributes = ('x', 5), ('y', 6), ('name', 'Cls') 

class Cls: 
    pass 
for key, value in attributes: 
    setattr(Cls, key, value) 

ricordare che per deve essere eseguito dopo l'intera classe è definita. Si ottiene errore, che attr non è definito, perché si desidera accedere alla classe prima dello che si crea (class ... è un'istruzione in python, che crea un oggetto classe). È necessario aggiungere attributi dopo aver creato una classe e ricordare, quelli saranno attributi di classe, non attributi di istanza.

1
class Attr: 
    def __init__(self): 
    for key in objects_type: 
     setattr(Attr, key, lambda cl: list()) 
+1

+1: Good. Perché non una classe "new style" che eredita da 'object'? –

+2

Questo è il posto sbagliato per farlo. Non solo è uno spreco, ma i metodi associati esistenti saranno diversi dai metodi associati da oggetti istanziati in seguito. Bene, più diverso del solito. –

2
newmeths = { 
    'two': lambda self: 2, 
} 

class MC(type): 
    def __init__(cls, name, bases, dict): 
    for k, v in newmeths.iteritems(): 
     setattr(cls, k, v) 
    super(MC, cls).__init__(name, bases, dict) 

class C(object): 
    __metaclass__ = MC 
    pass 

c=C() 
print c.two() 
3

supponiamo che si desidera aggiungere dinamicamente gli attributi di classe come questi

classDict = {} 
for i in range(2): 
    classDict["func%s"%(i+1)] = lambda self:"X" 

si può fare questo in diversi modi, ad es basta aggiungere attributi dopo la lezione è stata creata perché si can'y facilmente accedere nome di classe all'interno della classe

class Attr2(object): 
    pass 

for n,v in classDict.iteritems(): 
    setattr(Attr2, n, v) 

print Attr2().func1(), Attr2().func2() 

o meglio solo creare classe al volo esempio

Attr3 = type("Attr3",(), classDict) 
print Attr3().func1(), Attr3().func2() 

o se si desidera utilizzare metaclasse es

class AttrMeta(type): 
    def __new__(cls, name, bases, dct): 
     dct.update(classDict) 
     return type.__new__(cls, name, bases, dct) 

class Attr4(object): 
    __metaclass__ = AttrMeta 

print Attr4().func1(), Attr4().func2() 
+1

Penso che il metodo 'type' sia la soluzione migliore, data la domanda. Richiede al programmatore di ristrutturare il resto di come sono definiti gli attributi della classe. D'altra parte, evita di scavare in 'locals()', evita di definire una metaclasse personalizzata, ed evita il mucking con la logica di ogni _other_ metaclasse in uso. IMO, questo rende appetibile per una biblioteca che gli altri useranno e contribuiranno. – AlanSE