tutorial poo objetos python oop attributes iteration

poo - Iterar sobre los atributos del objeto en python



python poo tutorial (7)

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 una manera dinámica (por lo que si más tarde agrego otro atributo, no tengo que recordar actualizar también mi función).

En php, las variables se pueden usar como claves, pero los objetos en python no se pueden codificar y, si utilizo la notación de puntos para esto, creo 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.


Asumiendo que tienes una clase como

>>> class Cls(object): ... foo = 1 ... bar = ''hello'' ... def func(self): ... return ''call me'' ... >>> obj = Cls()

Llamar dir al 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.

>>> dir(obj) [''__class__'', ''__delattr__'', ''__dict__'', ''__doc__'', ''__format__'', ''__getattribute__'', ''__hash__'', ''__init__'', ''__module__'', ''__new__'', ''__reduce__'', ''__reduce_ex__'', ''__repr__'', ''__setattr__'', ''__sizeof__'', ''__str__'', ''__subclasshook__'', ''__weakref__'', ''bar'', ''foo'', ''func'']

Siempre puede filtrar los métodos especiales mediante el uso de una lista de comprensión.

>>> [a for a in dir(obj) if not a.startswith(''__'')] [''bar'', ''foo'', ''func'']

o si prefieres mapa / filtros

>>> filter(lambda a: not a.startswith(''__''), dir(obj)) [''bar'', ''foo'', ''func'']

Si desea filtrar los métodos, puede usar el builtin callable como verificación.

>>> [a for a in dir(obj) if not a.startswith(''__'') and not callable(getattr(obj,a))] [''bar'', ''foo'']

También puede inspeccionar la diferencia entre su clase y su padre usando.

>>> set(dir(Cls)) - set(dir(object)) set([''__module__'', ''bar'', ''func'', ''__dict__'', ''foo'', ''__weakref__''])


La respuesta correcta a esto es que no deberías. Si desea este tipo de cosas, simplemente use un dict o tendrá que agregar atributos explícitamente a algún contenedor. Puede automatizar eso aprendiendo sobre decoradores.

En particular, por cierto, method1 en su ejemplo es tan bueno como un atributo.


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 quiere una lista, también puede llamar a dir(obj) , que devuelve un iterable con todos los nombres de atributo, que luego podría pasar a getattr .

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?

class Foo(object): def __init__(self, **values): self.special_values = values

Luego puede iterar sobre las teclas con la for key in obj.special_values:


Para Python 3.6

class SomeClass: def attr_list(self, should_print=False): items = self.__dict__.items() if should_print: [print(f"attribute: {k} value: {v}") for k, v in items] return items


Para Python 3.6

class SomeClass: def attr_list1(self, should_print=False): for k in self.__dict__.keys(): v = self.__dict__.__getitem__(k) if should_print: print(f"attr: {k} value: {v}") def attr_list(self, should_print=False): b = [(k, v) for k, v in self.__dict__.items()] if should_print: [print(f"attr: {a[0]} value: {a[1]}") for a in b] return b


en general, ponga un método __iter__ en su clase e itere a través de los atributos del objeto o coloque esta clase mixin en su clase.

class IterMixin(object): def __iter__(self): for attr, value in self.__dict__.iteritems(): yield attr, value

Tu clase:

>>> class YourClass(IterMixin): pass ... >>> yc = YourClass() >>> yc.one = range(15) >>> yc.two = ''test'' >>> dict(yc) {''one'': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], ''two'': ''test''}


class someclass: x=1 y=2 z=3 def __init__(self): self.current_idx = 0 self.items = ["x","y","z"] def next(self): if self.current_idx < len(self.items): self.current_idx += 1 k = self.items[self.current_idx-1] return (k,getattr(self,k)) else: raise StopIteration def __iter__(self): return self

entonces solo llámalo como un iterable

s=someclass() for k,v in s: print k,"=",v