2010-02-15 12 views
8

yo estaba tratando de generar una clase de un diccionario:clase Adición de atributos utilizando un bucle en Python

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

Esto da el error que attr no está definido durante el bucle. Sé que podría escribir:

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

Pero estoy seguro de que recuerdo haber visto un código similar al primer ejemplo en alguna parte. ¿Alguien sabe si es posible escribir algo similar a la primera forma?

Respuesta

6

Aunque no es muy elegante, puede utilizar locals():

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

Eso debe haber sido lo que recuerdo haber visto. Gracias – Casebash

+0

De hecho, creo que es mejor que usar setattr, así que no diría que es poco elegante. – Casebash

+6

No se supone que cambies el dictus local() dict: http://docs.python.org/library/functions .html # locals – stephan

2

No sé exactamente qué estás haciendo. Te puedo dar ejemplo de cómo agregar atributos de clase a una clase en un bucle for:

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

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

recordar que para debe ejecutarse después de definir la clase entera. Obtiene el error, que attr no está definido, porque desea acceder a la clase antes de crearlo (class ... es una declaración en python, que crea un objeto de clase). Debe agregar atributos después de crear una clase y un recordador, esos serán atributos de clase, no atributos de instancia.

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

+1: Buena. ¿Por qué no una clase de "nuevo estilo" que hereda de 'object'? –

+2

Este es el lugar equivocado para hacer esto. No solo es un desperdicio, sino que los métodos enlazados existentes serán diferentes de los métodos enlazados de los objetos instanciados más tarde. Bueno, más diferente de lo habitual. –

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

supongamos que desea añadir dinámicamente los atributos de clase como estos

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

Usted puede hacer esto de varias maneras, por ejemplo sólo tiene que añadir atributos después de la clase ha sido creada porque can'y acceder fácilmente a nombre de la clase dentro de la clase

class Attr2(object): 
    pass 

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

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

o mejor basta con crear la clase sobre la marcha, por ejemplo,

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

o si desea utilizar metaclase por ejemplo

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

Creo que el método 'tipo' es la mejor solución, dada la pregunta. Requiere que el programador reestructure el resto de cómo se definen los atributos de la clase. Por otro lado, evita excavar en 'locals()', evita definir una metaclase personalizada y evita el borrado con la lógica de cualquier otra metaclases en uso. OMI, esto hace que sea aceptable para una biblioteca que otros usarán y contribuirán. – AlanSE

Cuestiones relacionadas