Eu tenho um objeto python com vários atributos e métodos. Eu quero iterar sobre os atributos do objeto.
class my_python_obj(object):
attr1='a'
attr2='b'
attr3='c'
def method1(self, etc, etc):
#Statements
Quero gerar um dicionário que contenha todos os atributos dos objetos e seus valores atuais, mas quero fazê-lo de maneira dinâmica (se mais tarde adicionar outro atributo, não preciso me lembrar de atualizar também minha função).
No php, variáveis podem ser usadas como chaves, mas os objetos em python são indescritíveis e, se eu usar a notação de ponto, cria um novo atributo com o nome da minha var, que não é minha intenção.
Apenas para esclarecer as coisas:
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
Atualização: com atributos, quero dizer apenas as variáveis deste objeto, não os métodos.
python
oop
attributes
iteration
Pablo Mescher
fonte
fonte
predicate
argumento opcional para transmitir uma chamada que filtraria as funções (ligadas?) (que se livraria dos métodos).Respostas:
Supondo que você tenha uma classe como
chamar
dir
o objeto devolve todos os atributos desse objeto, incluindo atributos especiais do python. Embora alguns atributos do objeto possam ser chamados, como métodos.Você sempre pode filtrar os métodos especiais usando uma compreensão de lista.
ou se você preferir mapas / filtros.
Se você deseja filtrar os métodos, pode usar o built-in
callable
como uma verificação.Você também pode inspecionar a diferença entre sua classe e seu objeto de instância usando.
fonte
callable
outypes.MethodType
. O que acontece se eu adicionar um atributo chamado "_foo" que armazene algum resultado intermediário ou estrutura de dados interna? O que acontece se eu adicionar inofensivamente um atributo à classename
, digamos, e agora, de repente, ele for incluído._foo
ename
porque agora eles são atributos do objeto. Se você não deseja incluí-los, pode excluí-los na condição de compreensão da lista. O código acima é um idioma comum do python e uma maneira popular de examinar objetos python.dir()
apenas "mente" quando as metaclasses são aprovadas (um caso extremo) ou classes com atributos decorados por@DynamicClassAttribute
(outro caso extremo). Nos dois casos, chamar odirs()
wrapperinspect.getmembers()
resolve isso. Para objetos padrão, no entanto, a abordagem de compreensão da lista desta solução é absolutamente filtrada. O fato de alguns pythonistas classificá-la como uma "má idéia" me confunde, mas ... cada um na sua, suponho?em geral, coloque um
__iter__
método em sua classe e repita os atributos do objeto ou coloque essa classe mixin em sua classe.Sua classe:
fonte
one
etwo
é definido depoisyc = YourClass()
. A pergunta é sobre o loop através dos atributos existentesYourClass()
. Além disso, a herança daIterMixin
classe nem sempre está disponível como solução.vars(yc)
dá o mesmo resultado sem precisar herdar de outra classe.vars(yc)
é quase o mesmo, mas o dicionário retornado é o da instância__dict__
, portanto, a modificação será refletida na instância. Isso pode causar problemas se você não tomar cuidado, portanto o método acima pode ser melhor (às vezes, é mais fácil copiar o dicionário). Além disso, observe que, embora o dicionário retornado acima não seja da instância__dict__
, os valores são os mesmos, portanto, a modificação de quaisquer valores mutáveis ainda será refletida nos atributos da instância.Como já mencionado em algumas respostas / comentários, os objetos Python já armazenam um dicionário de seus atributos (os métodos não estão incluídos). Isso pode ser acessado como
__dict__
, mas a melhor maneira é usarvars
(a saída é a mesma). Observe que a modificação deste dicionário modificará os atributos na instância! Isso pode ser útil, mas também significa que você deve ter cuidado com a forma como usa este dicionário. Aqui está um exemplo rápido:Usar
dir(a)
é uma abordagem estranha, se não totalmente ruim, para esse problema. É bom se você realmente precisa iterar sobre todos os atributos e métodos da classe (incluindo métodos especiais como__init__
). No entanto, isso não parece ser o que você deseja, e até a resposta aceita é mal aplicada aplicando uma filtragem frágil para tentar remover métodos e deixar apenas os atributos; você pode ver como isso falharia para a classeA
definida acima.(o uso
__dict__
foi feito em algumas respostas, mas todos definem métodos desnecessários em vez de usá-lo diretamente. Apenas um comentário sugere o usovars
).fonte
a.b
uma classe personalizada ,B
entãovars(a)["b"] is a.b
, como seria de esperar; nada mais faria sentido (pensea.b
no açúcar sintáticoa.__dict__["b"]
). Se você tiverd = vars(a)
e chamarrepr(d)
, ele chamarárepr(d["b"])
como parte do retorno de sua própria repr-string, pois apenas a classeB
realmente sabe como deve ser representada como uma string.Objetos em python armazenam seus atributos (incluindo funções) em um ditado chamado
__dict__
. Você pode (mas geralmente não deveria) usar isso para acessar os atributos diretamente. Se você deseja apenas uma lista, também pode chamardir(obj)
, que retorna uma iterável com todos os nomes de atributos, para os quais você poderia passargetattr
.No entanto, a necessidade de fazer qualquer coisa com os nomes das variáveis geralmente é um design ruim. Por que não mantê-los em uma coleção?
Em seguida, você pode percorrer as teclas com
for key in obj.special_values:
fonte
então chame isso de iterável
fonte
A resposta correta para isso é que você não deveria. Se você deseja esse tipo de coisa, basta usar um dict, ou precisará adicionar explicitamente atributos a algum contêiner. Você pode automatizar isso aprendendo sobre decoradores.
Em particular, a propósito, o método1 no seu exemplo é tão bom quanto um atributo.
fonte
Para python 3.6
fonte
Por todos os fanáticos pitonianos por aí, tenho certeza de que Johan Cleeze aprovaria seu dogmatismo;). Estou deixando esta resposta, continuando a deméritá-la. Isso realmente me deixa mais confidente. Deixe um comentário, galinhas!
Para python 3.6
fonte