Quero obter os atributos de uma classe, diga:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
usando MyClass.__dict__
me dá uma lista de atributos e funções, e até funções como __module__
e __doc__
. Enquanto MyClass().__dict__
me dá um dicionário vazio, a menos que eu defina explicitamente um valor de atributo dessa instância.
Eu só quero os atributos, no exemplo acima, eles seriam: a
eb
python
python-2.7
class
attributes
Mohamed Khamis
fonte
fonte
Respostas:
Experimente o módulo de inspeção .
getmembers
e os vários testes devem ser úteis.EDITAR:
Por exemplo,
Agora, os métodos e atributos especiais me dão nos nervos - eles podem ser tratados de várias maneiras, a mais fácil das quais é apenas filtrar com base no nome.
... e o mais complicado dos quais pode incluir verificações de nomes de atributos especiais ou mesmo metaclasses;)
fonte
attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
print [a[0] for a in attributes if '_' not in a[0]]
like_this
! Isso também evitará atributos "privados", o que você pode ter feito de propósito.inspect.getmembers(MyClass, ...
,MyClass
pode ser substituído por uma classe ou um objeto, e se você precisar da lista dos valores de seus objetos, deve substituirMyClass
por sua variável de objeto (ouself
se você colocar esta expressão em umdef __repr__()
método como eu).i = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))); z = [_[1] for _ in i if _[0] in '__dict__'][0]
e então é apenas uma questão de obter as chaves de z.fonte
if not i.startswith('_')
vez deif i[:1] != '_'
?.__dict__.keys()
não incluiremos atributos do pai.myfunc
é um atributo deMyClass
. É assim que ele é encontrado quando você executa:Ele procura por um atributo no
myinstance
namedmyfunc
, não encontra nenhum, vê quemyinstance
é uma instância deMyClass
e procura lá em cima.Portanto, a lista completa de atributos para
MyClass
é:(Observe que estou usando dir apenas como uma maneira rápida e fácil de listar os membros da classe: ele deve ser usado apenas de forma exploratória, não em código de produção)
Se você só quer atributos particulares, você precisa filtrar essa lista usando alguns critérios, pois
__doc__
,__module__
emyfunc
não são especiais de alguma forma, eles são atributos exatamente da mesma forma quea
eb
são.Eu nunca usei o módulo inspect referido por Matt e Borealid, mas a partir de um breve link parece que ele tem testes para ajudá-lo a fazer isso, mas você precisará escrever sua própria função de predicado, uma vez que parece o que você deseja são aproximadamente os atributos que não passam no
isroutine
teste e não começam e terminam com dois sublinhados.Observe também: ao usar
class MyClass():
no Python 2.7, você está usando as classes de estilo antigo totalmente desatualizadas. A menos que você esteja fazendo isso deliberadamente para compatibilidade com bibliotecas extremamente antigas, você deve definir sua classe comoclass MyClass(object):
. No Python 3 não há classes "no estilo antigo" e esse comportamento é o padrão. No entanto, o uso de classes de estilo novo resultará em muito mais atributos definidos automaticamente:fonte
dir()
: " Como dir () é fornecido principalmente como uma conveniência para uso em um prompt interativo, ele tenta fornecer um conjunto interessante de nomes mais do que um conjunto de nomes definido de forma rigorosa ou consistente , e seus detalhes o comportamento pode mudar entre as versões . "(consulte a documentação dodir()
).Obter apenas os atributos da instância é fácil.
Mas obter também os atributos de classe sem as funções é um pouco mais complicado.
Atributos de instância apenas
Se você só precisa listar os atributos de instância, basta usar
for attribute, value in my_instance
.__dict__
.items()
Atributos de instância e classe
Para obter também os atributos de classe sem as funções, o truque é usar
callable()
.Mas os métodos estáticos nem sempre
callable
são !Portanto, em vez de usar
callable(value)
usecallable
(getattr
(MyClass, attribute))
Exemplo
Nota:
print_class_attributes()
deveria ser, mas não neste exemplo estúpido e simples .@staticmethod
Resultado para python2
Mesmo resultado para python3
fonte
MyClass().__class__.__dict__
No entanto, o "certo" era fazer isso por meio do módulo de inspeção .
fonte
MyClass().__class__.__dict__
==MyClass.__dict__
MyClass().__class__.__dict__ != MyClass().__dict__
, mas yak não está incluindo os parênteses do lado direito, caso esteja corretoPara uma instância de MyClass, como
use
type(mc)
no lugar deMyClass
na lista de compreensão. No entanto, se alguém adicionar dinamicamente um atributo amc
, comomc.c = "42"
, o atributo não aparecerá quando usadotype(mc)
nesta estratégia. Ele apenas fornece os atributos da classe original.Para obter o dicionário completo para uma instância de classe, você precisaria COMBINAR os dicionários de
type(mc).__dict__
emc.__dict__
.fonte
Não sei se algo semelhante foi feito até agora ou não, mas fiz uma boa função de pesquisa de atributos usando vars (). vars () cria um dicionário dos atributos de uma classe que você passa por ele.
Estou desenvolvendo uma grande aventura de texto em Python, minha classe Player até agora tem mais de 100 atributos. Eu uso isso para pesquisar atributos específicos que preciso ver.
fonte
Isso pode ser feito sem inspeção, eu acho.
Faça a seguinte aula:
Olhando para os membros junto com seus tipos:
... dá:
Portanto, para gerar apenas as variáveis, você só precisa filtrar os resultados por tipo e nomes que não começam com '__'. Por exemplo
É isso aí.
Nota: se você estiver usando Python 3, converta os iteradores em listas.
Se você quiser uma maneira mais robusta de fazer isso, use inspect .
fonte
Python 2 e 3, sem importações, filtrando objetos por seus endereços
Soluções resumidas:
Retorne dict {attribute_name: attribute_value} , objetos filtrados. ie
{'a': 1, 'b': (2, 2), 'c': [3, 3]}
Lista de retorno [attribute_names] , objetos filtrados. ie
['a', 'b', 'c', 'd']
Lista de retorno [attribute_values] , objetos filtrados. ie
[1, (2, 2), [3, 3], {4: 4}]
Não filtrando objetos
Removendo a
if
condição. Retorna{'a': 1, 'c': [3, 3], 'b': (2, 2), 'e': <function <lambda> at 0x7fc8a870fd70>, 'd': {4: 4}, 'f': <object object at 0x7fc8abe130e0>}
Solução em longo prazo
Desde que a implementação padrão de
__repr__
não seja substituída, aif
instrução retornaráTrue
se a representação hexadecimal do local na memória deval
estiver na__repr__
string de retorno.Em relação à implementação padrão de,
__repr__
você pode achar útil esta resposta . Em resumo:Que retorna uma string como:
A localização na memória de cada elemento é obtida por meio do
id()
método.Python Docs diz sobre id ():
Tente você mesmo
Resultado:
Nota :
Testado com Python
2.7.13
e Python3.5.3
Em Python 2.x
.iteritems()
é preferível.items()
fonte
Recentemente, precisei descobrir algo semelhante a esta questão, então queria postar algumas informações básicas que podem ser úteis para outras pessoas que enfrentem o mesmo no futuro.
Veja como funciona em Python (em https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy ):
MyClass
é um objeto de classe,MyClass()
é uma instância do objeto de classe. Uma instância__dict__
contém apenas atributos e métodos específicos para aquela instância (por exemploself.somethings
). Se um atributo ou método fizer parte de uma classe, está na classe__dict__
. Ao fazer issoMyClass().__dict__
, uma instância deMyClass
é criada sem atributos ou métodos além dos atributos de classe, portanto, o vazio__dict__
Portanto, se você disser
print(MyClass().b)
, Python primeiro verifica o dict da nova instânciaMyClass().__dict__['b']
e não consegue encontrarb
. Em seguida, verifica a classeMyClass.__dict__['b']
e encontrab
.É por isso que você precisa do
inspect
módulo, para emular o mesmo processo de pesquisa.fonte
Você pode usar
dir()
em uma compreensão de lista para obter os nomes dos atributos:Use
getattr()
para obter os próprios atributos:fonte
Minha solução para obter todos os atributos (não métodos) de uma classe (se a classe tiver uma docstring devidamente escrita que tenha os atributos claramente especificados):
Esta peça
cls.__dict__['__doc__']
extrai a docstring da classe.fonte
Por que você precisa listar os atributos? Parece que semanticamente sua classe é uma coleção. Nestes casos, recomendo usar enum:
Liste seus atributos? Nada mais fácil do que isso:
fonte
Se você deseja "obter" um atributo, há uma resposta muito simples , que deveria ser óbvia: getattr
Funciona muito bem no Python 2.7 e no Python 3.x.
Se você quiser uma lista desses itens, ainda precisará usar inspecionar.
fonte
duas funções:
usar:
fonte
O seguinte é o que eu quero.
Dados de teste
fonte
Eu sei que isso foi há três anos, mas para aqueles que virão por essa questão no futuro, para mim:
funciona muito bem.
fonte
attribute
é de antemão.Você pode usar
MyClass.__attrs__
. Ele apenas fornece todos os atributos dessa classe. Nada mais.fonte