Itérer sur les attributs de l'objet en python

j'ai un objet python avec plusieurs attributs et méthodes. Je veux itérer sur les attributs de l'objet.

class my_python_obj(object):
    attr1='a'
    attr2='b'
    attr3='c'

    def method1(self, etc, etc):
        #Statements

je veux générer un dictionnaire contenant tous les attributs des objets et leurs valeurs actuelles, mais je veux le faire d'une manière dynamique (donc si plus tard j'ajoute un autre attribut Je n'ai pas à me rappeler de mettre à jour ma fonction aussi bien).

dans les variables php peut être utilisé comme des clés, mais les objets en python sont inscriptibles et si j'utilise la notation par points, pour cela, il crée un nouvel attribut avec le nom de mon var, qui n'est pas mon intention.

Juste pour rendre les choses plus claires:

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

mise à jour: Avec les attributs Je veux dire seulement les variables de cet objet, pas les méthodes.

92
demandé sur Eric Leschinski 2012-07-24 22:44:55

7 réponses

si vous avez une classe comme

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

appel dir sur l'objet vous donne tous les attributs de l'objet, y compris python attributs particuliers. Bien que certains attributs d'objet soient appelables, tels que les méthodes.

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

Vous pouvez toujours filtrer les méthodes spéciales en utilisant une liste de compréhension.

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

ou si vous préférez carte/filtres.

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

Si vous souhaitez filtrer les méthodes, vous pouvez utiliser le builtin callable comme un chèque.

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

vous pouvez également inspecter la différence entre votre classe et son parent en utilisant.

>>> set(dir(Cls)) - set(dir(object))
set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])
154
répondu Meitham 2013-08-09 10:32:26

en général, mettez une méthode __iter__ dans votre classe et itérez les attributs de l'objet ou mettez cette classe mixin dans votre classe.

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

votre classe:

>>> 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'}
39
répondu SmartElectron 2013-11-26 10:29:39

les objets en python stockent leurs attributs (incluant les fonctions) dans un dict appelé __dict__ . Vous pouvez (mais généralement vous ne devriez pas) utiliser ceci pour accéder directement aux attributs. Si vous voulez juste une liste, vous pouvez aussi appeler dir(obj) , qui renvoie un itérable avec tous les noms d'attribut, que vous pourriez alors passer à getattr .

cependant, avoir besoin de faire quoi que ce soit avec les noms des variables est généralement une mauvaise conception. Pourquoi ne pas les garder dans une collection?

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

vous pouvez alors itérer sur les touches avec for key in obj.special_values:

2
répondu Daenyth 2012-07-24 18:56:16
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

alors il suffit de l'appeler comme un itérable

s=someclass()
for k,v in s:
    print k,"=",v
1
répondu Joran Beasley 2012-07-24 19:05:21

pour 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
1
répondu Rubber Duck 2018-03-09 16:23:39

pour 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
0
répondu Rubber Duck 2018-03-09 15:54:50

la bonne réponse est que vous ne devriez pas. Si vous voulez ce type de chose, utilisez simplement un dict, ou vous aurez besoin d'ajouter explicitement des attributs à un conteneur. Vous pouvez automatiser cela en apprenant sur les décorateurs.

En particulier, par la manière, method1 dans votre exemple est tout aussi bien d'un attribut.

-1
répondu Julian 2012-07-24 18:55:52