loop em todas as variáveis ​​de membro de uma classe em python


88

Como você obtém uma lista de todas as variáveis ​​em uma classe iterável? Mais ou menos como moradores (), mas para uma aula

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

    def as_list(self)
       ret = []
       for field in XXX:
           if getattr(self, field):
               ret.append(field)
       return ",".join(ret)

isso deve retornar

>>> e = Example()
>>> e.as_list()
bool143, bool2, foo

Por que não posso usar for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Como é que você não conhece as variáveis ​​de instância da classe?
S.Lott,

4
S.Lott: foi o que acabei fazendo de qualquer maneira. No meu código real, tenho cerca de 40 variáveis ​​e pensei que seria melhor e mais DRY não ter que fazer manualmente a lista de iterações.
priestc de

Respostas:


150
dir(obj)

fornece todos os atributos do objeto. Você mesmo precisa filtrar os membros de métodos etc.:

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

example = Example()
members = [attr for attr in dir(example) if not callable(getattr(example, attr)) and not attr.startswith("__")]
print members   

Darei à você:

['blah', 'bool143', 'bool2', 'foo', 'foobar2000']

8
por que instanciar um objeto: dir (Example ()) em vez de apenas o tipo de classe dir (Example)
Erdal

8
e como você obtém os valores?
knutole

7
@knutole: getattr (object, attr)
opello

8
Como callable(attr)funciona? Não é attruma corda?
cubuspl42

6
você deveria ter usado vars(Example).items()ou em vars(instance.__class__).items()vez de dir()se deseja verificar se é possível ou não, porque dir só retornará ' strings como nomes ..
rrw

116

Se você quiser apenas as variáveis ​​(sem funções), use:

vars(your_object)

5
Você ainda precisa filtrar vars, mas esta é a resposta correta
gaborous

2
realmente gosto dessa abordagem vou usá-lo para descobrir o que serializar antes de enviar estados pela rede, por exemplo ...
Thom

7
varsque não incluem as variáveis de classe, apenas as variáveis de instância.
DilithiumMatrix de

1
@DilithiumMatrix você precisa usar vars (THECLASSITSELF) na própria classe para obter variáveis ​​de classe. Verifique minha resposta abaixo.
AmirHossein

1
Usar este método para responder especificamente à pergunta do OP: members = list(vars(example).keys())as (pelo menos em python3) varsretorna um dictmapeamento do nome da variável de membro para seu valor.
Michael Hall de

28

@truppo: sua resposta está quase correta, mas chamável sempre retornará falso, já que você está apenas passando uma string. Você precisa de algo como o seguinte:

[attr for attr in dir(obj()) if not callable(getattr(obj(),attr)) and not attr.startswith("__")]

que irá filtrar funções


6
>>> a = Example()
>>> dir(a)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', 'bool143', 'bool2', 'blah',
'foo', 'foobar2000', 'as_list']

- como você vê, isso dá a você todos os atributos, então você terá que filtrar um pouco. Mas basicamente dir()é o que você está procurando.


-1
row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns} if r else {}

Usa isto.


Enganador. Não há atributo ' tabela ' nas classes por padrão.
ben26941

-2
    class Employee:
    '''
    This class creates class employee with three attributes 
    and one function or method
    '''

    def __init__(self, first, last, salary):
        self.first = first
        self.last = last
        self.salary = salary

    def fullname(self):
        fullname=self.first + ' ' + self.last
        return fullname

emp1 = Employee('Abhijeet', 'Pandey', 20000)
emp2 = Employee('John', 'Smith', 50000)

print('To get attributes of an instance', set(dir(emp1))-set(dir(Employee))) # you can now loop over

-3

A maneira fácil de fazer isso é salvar todas as instâncias da classe em a list.

a = Example()
b = Example()
all_examples = [ a, b ]

Os objetos não surgem espontaneamente. Alguma parte do seu programa os criou por um motivo. A criação é feita por um motivo. Colecioná-los em uma lista também pode ser feito por um motivo.

Se você usa uma fábrica, pode fazer isso.

class ExampleFactory( object ):
    def __init__( self ):
        self.all_examples= []
    def __call__( self, *args, **kw ):
        e = Example( *args, **kw )
        self.all_examples.append( e )
        return e
    def all( self ):
        return all_examples

makeExample= ExampleFactory()
a = makeExample()
b = makeExample()
for i in makeExample.all():
    print i

Gosto da ideia (posso até usar isso em um projeto atual). No entanto, não é uma resposta para a pergunta: o OP deseja listar os atributos, não as próprias instâncias.
balpha,

@balpha: Opa. Não li a pergunta. 90% das vezes, é uma duplicata de "como faço para encontrar todas as instâncias de uma classe." A questão real (agora que você a apontou) não faz sentido. Você conhece as variáveis ​​de instância, basta fazer uma lista.
S.Lott,
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.