Tengo un objeto python con varios atributos y métodos. Quiero iterar sobre los atributos del objeto.
class my_python_obj(object):
attr1='a'
attr2='b'
attr3='c'
def method1(self, etc, etc):
#Statements
Quiero generar un diccionario que contenga todos los atributos de los objetos y sus valores actuales, pero quiero hacerlo de forma dinámica (así que si luego agrego otro atributo, no tengo que recordar actualizar mi función también).
En php, las variables se pueden usar como claves, pero los objetos en python no se pueden usar y si uso la notación de punto para esto, crea un nuevo atributo con el nombre de mi var, que no es mi intención.
Solo para aclarar las cosas:
def to_dict(self):
'''this is what I already have'''
d={}
d["attr1"]= self.attr1
d["attr2"]= self.attr2
d["attr3"]= self.attr3
return d
·
def to_dict(self):
'''this is what I want to do'''
d={}
for v in my_python_obj.attributes:
d[v] = self.v
return d
Actualización: con atributos me refiero solo a las variables de este objeto, no a los métodos.
python
oop
attributes
iteration
Pablo Mescher
fuente
fuente
predicate
argumento opcional para pasar un invocable que filtraría (¿enlazado?) funciones (que elimina los métodos).Respuestas:
Asumiendo que tienes una clase como
invocar
dir
el objeto le devuelve todos los atributos de ese objeto, incluidos los atributos especiales de python. Aunque algunos atributos de objeto son invocables, como los métodos.Siempre puede filtrar los métodos especiales utilizando una lista de comprensión.
o si prefieres mapa / filtros.
Si desea filtrar los métodos, puede usar el incorporado
callable
como un cheque.También puede inspeccionar la diferencia entre su clase y su objeto de instancia utilizando.
fuente
callable
otypes.MethodType
. ¿Qué sucede si agrego un atributo llamado "_foo" que almacena algún resultado intermedio o estructura de datos interna? ¿Qué sucede si simplemente agrego un atributo a la clasename
, inadvertidamente, y ahora, de repente, se incluye?_foo
yname
porque ahora son atributos del objeto. Si no desea incluirlos, puede excluirlos en la condición de comprensión de la lista. El código anterior es un idioma común de Python y una forma popular de introspección de objetos de Python.dir()
solo "miente" cuando pasa metaclases (un caso extremo) o clases con atributos decorados por@DynamicClassAttribute
(otro caso extremo extremo). En ambos casos, llamar aldirs()
contenedorinspect.getmembers()
resuelve esto. Sin embargo, para los objetos estándar, el enfoque de comprensión de la lista de esta solución que filtra los no callables es absolutamente suficiente. Que algunos Pythonistas lo etiqueten como una "mala idea" me desconcierta, pero ... ¿a cada uno lo suyo, supongo?en general ponga un
__iter__
método en su clase e itere a través de los atributos del objeto o ponga esta clase mixin en su clase.Tu clase:
fuente
one
ytwo
se define despuésyc = YourClass()
. La pregunta se refiere a recorrer los atributos existentes enYourClass()
. Además, heredar laIterMixin
clase puede no estar siempre disponible como solución.vars(yc)
da el mismo resultado sin tener que heredar de otra clase.vars(yc)
es casi lo mismo, pero el diccionario que le devuelve es propio de la instancia__dict__
, por lo que modificarlo se reflejará en la instancia. Esto puede generar problemas si no tiene cuidado, por lo que el método anterior a veces podría ser mejor (aunque copiar el diccionario probablemente sea más fácil). Además, tenga en cuenta que si bien el diccionario devuelto anteriormente no es de la instancia__dict__
, los valores son los mismos, por lo que la modificación de cualquier valor mutable se reflejará en los atributos de la instancia.Como ya se mencionó en algunas de las respuestas / comentarios, los objetos de Python ya almacenan un diccionario de sus atributos (los métodos no están incluidos). Se puede acceder a esto como
__dict__
, pero la mejor manera es usarlovars
(sin embargo, la salida es la misma). ¡Tenga en cuenta que la modificación de este diccionario modificará los atributos en la instancia! Esto puede ser útil, pero también significa que debe tener cuidado con la forma en que usa este diccionario. Aquí hay un ejemplo rápido:El uso
dir(a)
es un enfoque extraño, si no totalmente malo, para este problema. Es bueno si realmente necesita iterar sobre todos los atributos y métodos de la clase (incluidos los métodos especiales como__init__
). Sin embargo, esto no parece ser lo que desea, e incluso la respuesta aceptada es pobre al aplicar un filtro frágil para tratar de eliminar métodos y dejar solo los atributos; puede ver cómo esto fallaría para la claseA
definida anteriormente.(el uso
__dict__
se ha realizado en un par de respuestas, pero todas definen métodos innecesarios en lugar de usarlo directamente. Solo un comentario sugiere usarvars
).fuente
a.b
alguna clase personalizada,B
entoncesvars(a)["b"] is a.b
, como cabría esperar; nada más tendría sentido (piensea.b
en azúcar sintácticoa.__dict__["b"]
). Si tiened = vars(a)
y llamarepr(d)
, llamarárepr(d["b"])
como parte de devolver su propia cadena de reproducción, ya que solo la claseB
realmente sabe cómo debe representarse como una cadena.Los objetos en python almacenan sus atributos (incluidas las funciones) en un dict llamado
__dict__
. Puede (pero generalmente no debería) usar esto para acceder a los atributos directamente. Si solo desea una lista, también puede llamardir(obj)
, que devuelve un iterable con todos los nombres de atributos, que luego puede pasargetattr
.Sin embargo, la necesidad de hacer algo con los nombres de las variables suele ser un mal diseño. ¿Por qué no mantenerlos en una colección?
Luego puede iterar sobre las teclas con
for key in obj.special_values:
fuente
entonces solo llámalo como iterable
fuente
La respuesta correcta a esto es que no deberías. Si desea este tipo de cosas, simplemente use un dict, o deberá agregar explícitamente atributos a algún contenedor. Puede automatizar eso aprendiendo sobre decoradores.
En particular, por cierto, método1 en su ejemplo es tan bueno de un atributo.
fuente
Para python 3.6
fuente
Por todos los fanáticos pitonianos que existen, estoy seguro de que Johan Cleeze aprobaría su dogmatismo;). Dejo esta respuesta y la sigo demoriendo. De hecho, me hace más confidente. Deja un comentario gallinas!
Para python 3.6
fuente