Quiero crear un objeto dinámico (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 for
bucle que recorre una lista de valores, por ejemplo
params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()
for p in params:
obj.a.p # where p comes from for loop variable
En el ejemplo anterior me gustaría conseguir obj.a.attr1
, obj.a.attr2
, obj.a.attr3
.
Usé la setattr
función porque no sabía cómo hacerlo obj.a.NAME
desde un for
bucle.
¿Cómo establecería el atributo en función del valor de p
en el ejemplo anterior?
python
class
object
attributes
Juan
fuente
fuente
a = object()
y lo necesitasobj.a = object()
. Nuevamente, estoy hablando del ejemplo, en su código real, un objeto dentro de un objeto podría ser útil.Respuestas:
Podrías usar mi antigua receta Bunch , pero si no quieres hacer una "clase de grupo", ya existe una muy simple en Python: todas las funciones pueden tener atributos arbitrarios (incluidas las funciones lambda). Entonces, lo siguiente funciona:
Si la pérdida de claridad en comparación con la
Bunch
receta venerable está bien, es una decisión de estilo que, por supuesto, dejaré en sus manos.fuente
lambda: 23
), por lo que a dichos expertos usanlambda
s para este propósito presumiblemente no sentiría nada como "un hack". Personalmente, no me gusta mucholambda
Python , pero eso es en gran medida un problema de gusto personal.lambda
patrón se ajusta o no a su caso de uso puede llevarlo a darse cuenta de que algo que originalmente pensó como datos es en realidad más como una función, o, en cualquier caso, un functor.from argparse import Namespace
aunque desearía que viviera en otro lugar *, por ejemplo,collection
) - nuevamente reutilizando un tipo ahora existente, solo uno mejor, y aún evitando la creación de nuevos tipos. Pero, no estaba allí entonces :-).El incorporado
object
puede ser instanciado pero no puede tener ningún atributo establecido en él. (Ojalá pudiera, para este propósito exacto). No tiene__dict__
que contener los atributos.Generalmente solo hago esto:
Cuando puedo, le doy a la
Object
clase un nombre más significativo, dependiendo de qué tipo de datos estoy poniendo.Algunas personas hacen algo diferente, donde usan una subclase
dict
que permite el acceso a los atributos para obtener las teclas. (end.key
lugar ded['key']
)Editar : para agregar a su pregunta, usar
setattr
está bien. Simplemente no se puede usarsetattr
enobject()
instancias.fuente
foo = object()
funciona, pero simplemente no puedes hacer nada con éltype....
o lambda nunca fue mi favorito, como el vómito de texto en mi código. Pero esta idea es excelente para usar objetos para mantener propiedades. Deja el código más legible b / c cuando veo lambda. ¡Disminuyo mi lectura al 25% mientras tu camino tiene sentido! Gracias.Struct
como nombre de la clase para hacerlo más obvio. Me ahorró un montón de mecanografía["
y"]
, ¡salud!Hay
types.SimpleNamespace
clase en Python 3.3+ :collections.namedtuple
,typing.NamedTuple
podría usarse para objetos inmutables. PEP 557: las clases de datos sugieren una alternativa mutable.Para una funcionalidad más rica, puedes probar el
attrs
paquete . Vea un ejemplo de uso .fuente
argparse.Namespace
claseattrs
paquete @Roel admite Python 2.7Hay algunas formas de alcanzar este objetivo. Básicamente necesitas un objeto que sea extensible.
fuente
obj.a = type('', (), {})
El
mock
módulo está básicamente hecho para eso.fuente
unittest.Mock
es parte de la biblioteca estándar desde Python 3.3 ( docs.python.org/3/library/unittest.mock.html )mock
. Solo se siente raro para mí.Ahora puedes hacerlo (no estoy seguro si es la misma respuesta que evilpie):
fuente
Prueba el siguiente código:
fuente
También puede usar un objeto de clase directamente; crea un espacio de nombres:
fuente
como dicen los documentos :
Podrías usar una instancia de clase ficticia.
fuente
Estas soluciones son muy útiles durante las pruebas. Basándome en 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 independiente ...):
fuente
¿Qué objetos estás usando? Solo intenté eso con una clase de muestra y funcionó bien:
Y obtuve
123
la respuesta.La única situación en la que veo que esto falla es si estás probando un
setattr
objeto incorporado.Actualización: Del comentario, esta es una repetición de: ¿Por qué no puedes agregar atributos al objeto en Python?
fuente
Llegando a esto tarde en el día, pero aquí está mi pennyworth con un objeto que simplemente contiene algunas rutas útiles en una aplicación, pero puede adaptarlo para cualquier cosa donde desee un tipo de información a la que pueda acceder con getattr y notación de puntos (que es de lo que creo que se trata realmente esta pregunta):
Esto es genial porque ahora:
Por lo tanto, esto usa el objeto de función como las respuestas anteriores, pero usa la función para obtener los valores (aún puede usar en
(getattr, x_path, 'repository')
lugar dex_path('repository')
si lo prefiere).fuente
Si podemos determinar y agregar todos los atributos y valores juntos antes de crear el objeto anidado, entonces podríamos crear una nueva clase que tome un argumento de diccionario en la creación.
También podemos permitir argumentos de palabras clave. Ver este post .
fuente
fuente
De otra manera veo, de esta manera:
fuente
class a: pass
brinda toda la potencia requerida.