¿Cómo puedo crear un objeto y agregarle atributos?

Quiero crear un objeto dynamic (dentro de otro objeto) en Python y luego agregarle atributos.

Lo intenté:

obj = someobject obj.a = object() setattr(obj.a, 'somefield', 'somevalue') 

pero esto no funcionó.

¿Algunas ideas?

editar:

Estoy configurando los atributos de un bucle for que recorre una lista de valores, por ejemplo

 params = ['attr1', 'attr2', 'attr3'] obj = someobject obj.a = object() for p in params: obj.ap # where p comes from for loop variable 

En el ejemplo anterior obtendría obj.a.attr1 , obj.a.attr2 , obj.a.attr3 .

Utilicé la función setattr porque no sabía cómo hacer obj.a.NAME desde un bucle for .

¿Cómo establecería el atributo según el valor de p en el ejemplo anterior?

Podría usar mi antigua receta de Bunch , pero si no quiere hacer una “clase de manojo”, ya existe una muy simple en Python: todas las funciones pueden tener atributos arbitrarios (incluidas las funciones lambda). Así, los siguientes trabajos:

 obj = someobject obj.a = lambda: None setattr(obj.a, 'somefield', 'somevalue') 

Si la pérdida de claridad en comparación con la venerable receta de Bunch está bien, es una decisión de estilo que, por supuesto, le dejaré a usted.

El object incorporado puede ser instanciado pero no puede tener ningún atributo establecido en él. (Desearía que pudiera, para este propósito exacto). No tiene un __dict__ para mantener los atributos.

Generalmente solo hago esto:

 class Object(object): pass a = Object() a.somefield = somevalue 

Cuando puedo, le doy a la clase Object un nombre más significativo, dependiendo de qué tipo de datos estoy ingresando.

Algunas personas hacen una cosa diferente, donde usan una subclase de dict que permite el acceso de atributos para obtener las claves. ( d.key lugar de d['key'] )

Editar : Para agregar a su pregunta, usar setattr está bien. Simplemente no puede usar setattr en setattr de object() .

 params = ['attr1', 'attr2', 'attr3'] for p in params: setattr(obj.a, p, value) 

Hay clases de types.SimpleNamespace en Python 3.3+ :

 obj = someobject obj.a = SimpleNamespace() for p in params: setattr(obj.a, p, value) # obj.a.attr1 

collections.namedtuple , typing.NamedTuple podría usarse para objetos inmutables. PEP 557 – Clases de datos sugiere una alternativa mutable.

Para una funcionalidad más rica, puede probar el paquete attrs . Ver un ejemplo de uso .

Hay algunas maneras de alcanzar este objective. Básicamente necesitas un objeto que sea extensible.

 obj.a = type('Test', (object,), {}) obj.ab = 'fun' obj.b = lambda:None class Test: pass obj.c = Test() 

Ahora puedes hacerlo (no estoy seguro de si es la misma respuesta que evilpie):

 MyObject = type('MyObject', (object,), {}) obj = MyObject() obj.value = 42 

El módulo mock está hecho básicamente para eso.

 import mock obj = mock.Mock() obj.a = 5 

Pruebe el siguiente código:

 $ python >>> class Container(object): ... pass ... >>> x = Container() >>> xa = 10 >>> xb = 20 >>> x.banana = 100 >>> xa, xb, x.banana (10, 20, 100) >>> dir(x) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana'] 

También puedes usar un objeto de clase directamente; crea un espacio de nombres:

 class a: pass a.somefield1 = 'somevalue1' setattr(a, 'somefield2', 'somevalue2') 

como dicen los doctores :

Nota : el object no tiene un __dict__ , por lo que no puede asignar atributos arbitrarios a una instancia de la clase de object .

Puedes usar una instancia de clase ficticia.

Estas soluciones son muy útiles durante las pruebas. Sobre la base de las respuestas de todos los demás, hago esto en Python 2.7.9 (sin el método estático, obtengo un TypeError (método no vinculado …):

 In [11]: auth = type('', (), {}) In [12]: auth.func = staticmethod(lambda i: i * 2) In [13]: auth.func(2) Out[13]: 4 

¿Qué objetos estás usando? Solo probé eso con una clase de muestra y funcionó bien:

 class MyClass: i = 123456 def f(self): return "hello world" b = MyClass() bc = MyClass() setattr(bc, 'test', 123) bctest 

Y tengo 123 como respuesta.

La única situación en la que veo este setattr es si está intentando establecer un setattr en un objeto incorporado.

Actualización: a partir del comentario, esto es una repetición de: ¿Por qué no puedes agregar atributos al objeto en Python?

Llegando a esta hora avanzada, pero aquí está mi pennyworth con un objeto que por casualidad contiene algunas rutas útiles en una aplicación, pero puede adaptarlo para cualquier cosa en la que desee una cierta cantidad de información a la que pueda acceder con getattr y la notación de puntos. (que es de lo que creo que se trata realmente esta pregunta):

 import os def x_path(path_name): return getattr(x_path, path_name) x_path.root = '/home/x' for name in ['repository', 'caches', 'projects']: setattr(x_path, name, os.path.join(x_path.root, name)) 

Esto es genial porque ahora:

 In [1]: x_path.projects Out[1]: '/home/x/projects' In [2]: x_path('caches') Out[2]: '/home/x/caches' 

Por lo tanto, utiliza el objeto de función como las respuestas anteriores pero usa la función para obtener los valores (si lo prefiere, puede usar (getattr, x_path, 'repository') lugar de x_path('repository') si lo prefiere.

Si podemos determinar y agregar todos los atributos y valores juntos antes de crear el objeto nested, entonces podríamos crear una nueva clase que tome un argumento de diccionario en la creación.

 # python 2.7 class NestedObject(): def __init__(self, initial_attrs): for key in initial_attrs: setattr(self, key, initial_attrs[key]) obj = someobject attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' } obj.a = NestedObject(attributes) >>> obj.a.attr1 'val1' >>> obj.a.attr2 'val2' >>> obj.a.attr3 'val3' 

También podemos permitir argumentos de palabras clave. Ver este post

 class NestedObject(object): def __init__(self, *initial_attrs, **kwargs): for dictionary in initial_attrs: for key in dictionary: setattr(self, key, dictionary[key]) for key in kwargs: setattr(self, key, kwargs[key]) obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3') 
 di = {} for x in range(20): name = '_id%s' % x di[name] = type(name, (object), {}) setattr(di[name], "attr", "value") 

De otra manera veo, de esta manera:

 import maya.cmds def getData(objets=None, attrs=None): di = {} for obj in objets: name = str(obj) di[name]=[] for at in attrs: di[name].append(cmds.getAttr(name+'.'+at)[0]) return di acns=cmds.ls('L_vest_*_',type='aimConstraint') attrs=['offset','aimVector','upVector','worldUpVector'] getData(acns,attrs)