Existe uma função interna para imprimir todas as propriedades e valores atuais de um objeto?


Respostas:


591

Você está realmente misturando duas coisas diferentes.

Use dir(), vars()ou o inspectmódulo para conseguir o que você está interessado em (eu uso __builtins__como um exemplo, você pode usar qualquer objeto em seu lugar).

>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__

Imprima esse dicionário da maneira que desejar:

>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...

ou

>>> from pprint import pprint
>>> pprint(l)
['ArithmeticError',
 'AssertionError',
 'AttributeError',
 'BaseException',
 'DeprecationWarning',
...

>>> pprint(d, indent=2)
{ 'ArithmeticError': <type 'exceptions.ArithmeticError'>,
  'AssertionError': <type 'exceptions.AssertionError'>,
  'AttributeError': <type 'exceptions.AttributeError'>,
...
  '_': [ 'ArithmeticError',
         'AssertionError',
         'AttributeError',
         'BaseException',
         'DeprecationWarning',
...

A impressão bonita também está disponível no depurador interativo como um comando:

(Pdb) pp vars()
{'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>,
                  'AssertionError': <type 'exceptions.AssertionError'>,
                  'AttributeError': <type 'exceptions.AttributeError'>,
                  'BaseException': <type 'exceptions.BaseException'>,
                  'BufferError': <type 'exceptions.BufferError'>,
                  ...
                  'zip': <built-in function zip>},
 '__file__': 'pass.py',
 '__name__': '__main__'}

28
Surpreendentemente, parece que nem todos os objetos têm um __dict__membro ( re.MatchObjectpor exemplo), mas o builtin dir()funciona para todos os objetos.
Placas

print re.compile(r'slots').search('No slots here either.').__slots__
Placas

3
Novo para mim. Valeu. O ponto acionou o analisador de caminho do módulo do meu cérebro. Nunca considerou o "módulo" latino.
Placas

4
por que você não fala mais sobre o inspectmódulo em sua resposta? Eu acho que é a coisa mais próxima de print_r ou var_dump.
Hai Phaikawl

1
Como você acessa os valores por trás dos atributos listados por dir(), então? dir()retorna apenas uma lista de nomes e nem todos existem no vars()ou no __dict__atributo
HelloGoodbye 9/08/19

981

Você quer vars()misturado com pprint():

from pprint import pprint
pprint(vars(your_object))

24
vars()simplesmente retorna o __dict__argumento e esse também é o substituto dir()no caso de não haver __dir__método. então use dir()em primeiro lugar, como eu disse.

28
@hop: dir()fornece todas as coisas incorporadas que você provavelmente não gosta __str__e gosta __new__. var()não.
Timmmm 31/07/12

14
Isso falha em conjuntos e outros objetos que não têm __dict__atributo.
Anatoly techtonik

209
def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

Existem muitas funções de terceiros por aí que adicionam itens como tratamento de exceções, impressão de caracteres nacionais / especiais, recorrência em objetos aninhados etc. de acordo com as preferências de seus autores. Mas todos eles basicamente se resumem a isso.


5
não sintético, porque segue não-inventado aqui

14
Diga o quê? Claro, você pode usar a getmembers()função no inspectmódulo padrão , mas achei que isso seria mais útil, pois ilustra como fazer a introspecção em geral.
10898 Dan Lenski

20
DE MODO NENHUM. dir (obj) mostra propriedades que não são encontradas em __dict__(como __doc__e __module__). Além disso, __dict__não funciona para objetos declarados com __slots__. Em geral, __dict__mostra propriedades no nível do usuário que são realmente armazenadas internamente em um dicionário. dir () mostra mais.
10118 Dan Lenski

8
Algumas classes / objetos não contêm nenhum __dict__atributo / membro. Eu sei que é loucura, mas é verdade. Built-ins como inte strou re.MatchObjects são exemplos comuns. Tente 'hello'.__dict__, então tentedir('hello')
hobs

11
Eu não me importo se isso é «não-tônico» ou não. Ele realiza o trabalho, que na depuração é a única coisa que importa.
hidefromkgb

59

dir foi mencionado, mas isso fornecerá apenas os nomes dos atributos. Se você quiser os valores deles, tente __dict__.

class O:
   def __init__ (self):
      self.value = 3

o = O()

Aqui está a saída:

>>> o.__dict__

{'value': 3}

9
Objetos como setnão tem __dict__, por isso, para eles ele falhará comAttributeError: 'set' object has no attribute '__dict__'
techtonik anatoly

23

Você pode usar a função "dir ()" para fazer isso.

>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdo
t__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder
, 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_clear', 'exc_info'
 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefault
ncoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'he
version', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_
ache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
, 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoption
', 'winver']
>>>

Outro recurso útil é a ajuda.

>>> help(sys)
Help on built-in module sys:

NAME
    sys

FILE
    (built-in)

MODULE DOCS
    http://www.python.org/doc/current/lib/module-sys.html

DESCRIPTION
    This module provides access to some objects used or maintained by the
    interpreter and to functions that interact strongly with the interpreter.

    Dynamic objects:

    argv -- command line arguments; argv[0] is the script pathname if known

22

Para imprimir o estado atual do objeto, você pode:

>>> obj # in an interpreter

ou

print repr(obj) # in a script

ou

print obj

Para suas classes, defina __str__ou __repr__métodos. Na documentação do Python :

__repr__(self)Chamado pela repr()função interna e por conversões de string (aspas reversas) para calcular a representação de string "oficial" de um objeto. Se possível, deve parecer uma expressão Python válida que possa ser usada para recriar um objeto com o mesmo valor (considerando um ambiente apropriado). Se isso não for possível, uma sequência no formato "<... alguma descrição útil ...>" deve ser retornada. O valor de retorno deve ser um objeto de sequência. Se uma classe define repr () mas não __str__(), então__repr__() também é usado quando uma representação de cadeia "informal" de instâncias dessa classe é necessária. Isso geralmente é usado para depuração, por isso é importante que a representação seja rica em informações e inequívoca.

__str__(self)Chamado pela str()função interna e pela instrução print para calcular a representação de cadeia "informal" de um objeto. Isso difere do __repr__()fato de não precisar ser uma expressão válida do Python: uma representação mais conveniente ou concisa pode ser usada. O valor de retorno deve ser um objeto de sequência.


Esta opção é útil para imprimir seqüências de caracteres concatenadas com o conteúdo do objeto:print "DEBUG: object value: " + repr(obj)
AlejandroVD

17

Pode valer a pena conferir --

Existe um Python equivalente ao Data :: Dumper do Perl?

Minha recomendação é esta -

https://gist.github.com/1071857

Observe que o perl possui um módulo chamado Data :: Dumper, que converte os dados do objeto de volta ao código-fonte perl (NB: NÃO converte o código de volta ao código-fonte, e quase sempre você não deseja que o método de objeto funcione na saída). Isso pode ser usado para persistência, mas o objetivo comum é a depuração.

Há várias coisas que o python pprint padrão não consegue, em particular, ele apenas para de descer quando vê uma instância de um objeto e fornece o ponteiro hexadecimal interno do objeto (errr, esse ponteiro não é muito usado por o caminho). Então, em poucas palavras, python é tudo sobre esse ótimo paradigma orientado a objetos, mas as ferramentas que você obtém da caixa são projetadas para trabalhar com algo diferente de objetos.

O perl Data :: Dumper permite controlar a profundidade que você deseja ir e também detecta estruturas circulares vinculadas (isso é realmente importante). Esse processo é fundamentalmente mais fácil de ser realizado em perl, porque os objetos não têm mágica em particular além de suas bênçãos (um processo universalmente bem definido).


Isso deve ser um pip e um deb, não apenas uma essência!
Phobie

2
> Então, em poucas palavras, python é tudo sobre esse ótimo paradigma orientado a objetos, mas as ferramentas que você obtém da caixa são projetadas para trabalhar com algo diferente de objetos ... Uma afirmação bastante quando o único exemplo que você está fornecendo é um módulo de importância secundária.
Memeplex

@memeplex, onde diz que python é tudo sobre OOP?
Peter Wood

Ok, apenas diz que é tudo sobre esse ótimo POO, meu mal.
Memeplex

13

Eu recomendo usar help(your_object).

help(dir)

 If called without an argument, return the names in the current scope.
 Else, return an alphabetized list of names comprising (some of) the attributes
 of the given object, and of attributes reachable from it.
 If the object supplies a method named __dir__, it will be used; otherwise
 the default dir() logic is used and returns:
 for a module object: the module's attributes.
 for a class object:  its attributes, and recursively the attributes
 of its bases.
 for any other object: its attributes, its class's attributes, and
 recursively the attributes of its class's base classes.

help(vars)

Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.

Ah, cara, +100500
Kirby

12

Na maioria dos casos, usar __dict__ou dir()obterá as informações desejadas. Se precisar de mais detalhes, a biblioteca padrão inclui o módulo de inspeção , que permite obter uma quantidade impressionante de detalhes. Alguns dos verdadeiros nuggests de informações incluem:

  • nomes de parâmetros de função e método
  • hierarquias de classe
  • código fonte da implementação de uma função / objetos de classe
  • variáveis ​​locais fora de um objeto de quadro

Se você está apenas procurando "quais valores de atributo meu objeto possui?", Então dir()e __dict__provavelmente são suficientes. Se você está realmente procurando cavar o estado atual de objetos arbitrários (tendo em mente que em python quase tudo é um objeto), então inspecté digno de consideração.


Usei sua explicação no inspecionar para melhorar a resposta mais completa. Espero que esteja tudo bem com você.
Fernando César

9

Existe uma função interna para imprimir todas as propriedades e valores atuais de um objeto?

Não. A resposta mais votada exclui alguns tipos de atributos e a resposta aceita mostra como obter todos os atributos, incluindo métodos e partes da API não pública. Mas não há nenhuma boa completo builtin função para isso.

Portanto, o corolário curto é que você pode escrever seu próprio, mas ele calculará propriedades e outros descritores de dados calculados que fazem parte da API pública, e talvez você não queira isso:

from pprint import pprint
from inspect import getmembers
from types import FunctionType

def attributes(obj):
    disallowed_names = {
      name for name, value in getmembers(type(obj)) 
        if isinstance(value, FunctionType)}
    return {
      name: getattr(obj, name) for name in dir(obj) 
        if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}

def print_attributes(obj):
    pprint(attributes(obj))

Problemas com outras respostas

Observe a aplicação da resposta atualmente mais votada em uma classe com muitos tipos diferentes de membros de dados:

from pprint import pprint

class Obj:
    __slots__ = 'foo', 'bar', '__dict__'
    def __init__(self, baz):
        self.foo = ''
        self.bar = 0
        self.baz = baz
    @property
    def quux(self):
        return self.foo * self.bar

obj = Obj('baz')
pprint(vars(obj))

apenas imprime:

{'baz': 'baz'}

Como retorna vars apenas o __dict__de um objeto e não é uma cópia, por isso, se você modificar o ditado retornado por vars, também estará modificando o __dict__próprio objeto.

vars(obj)['quux'] = 'WHAT?!'
vars(obj)

retorna:

{'baz': 'baz', 'quux': 'WHAT?!'}

- o que é ruim porque o quux é uma propriedade que não devemos definir e não deve estar no espaço para nome ...

A aplicação do conselho na resposta atualmente aceita (e outras) não é muito melhor:

>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar', 'baz', 'foo', 'quux']

Como podemos ver, dirapenas retorna todos (na verdade, apenas a maioria) dos nomes associados a um objeto.

inspect.getmembers, mencionado nos comentários, é igualmente falho - retorna todos os nomes e valores.

Da classe

Ao ensinar, meus alunos criam uma função que fornece a API semanticamente pública de um objeto:

def api(obj):
    return [name for name in dir(obj) if name[0] != '_']

Podemos estender isso para fornecer uma cópia do espaço de nomes semântico de um objeto, mas precisamos excluir os __slots__que não foram atribuídos e, se levarmos a sério o pedido de "propriedades atuais", precisamos excluir as propriedades calculadas (como eles podem se tornar caros e podem ser interpretados como não "atuais"):

from types import FunctionType
from inspect import getmembers

def attrs(obj):
     disallowed_properties = {
       name for name, value in getmembers(type(obj)) 
         if isinstance(value, (property, FunctionType))}
     return {
       name: getattr(obj, name) for name in api(obj) 
         if name not in disallowed_properties and hasattr(obj, name)}

E agora não calculamos ou mostramos a propriedade, quux:

>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}

Ressalvas

Mas talvez saibamos que nossas propriedades não são caras. Podemos querer alterar a lógica para incluí-los também. E talvez desejemos excluir outro costume descritores de dados .

Então, precisamos personalizar ainda mais essa função. E, portanto, faz sentido que não possamos ter uma função interna que saiba magicamente exatamente o que queremos e a forneça. Essa é a funcionalidade que precisamos criar para nós mesmos.

Conclusão

Não existe uma função interna que faça isso, e você deve fazer o que é semanticamente mais apropriado para sua situação.


Há um parêntese extra próximo depois FunctionType. Mas muito útil - obrigado!
nealmcb 03/04

@nealmcb obrigado Eu acho que entendi. Fico feliz em estar de serviço! :)
Aaron Hall

7

Um exemplo de metaprogramação Despejar objeto com magia :

$ cat dump.py
#!/usr/bin/python
import sys
if len(sys.argv) > 2:
    module, metaklass  = sys.argv[1:3]
    m = __import__(module, globals(), locals(), [metaklass])
    __metaclass__ = getattr(m, metaklass)

class Data:
    def __init__(self):
        self.num = 38
        self.lst = ['a','b','c']
        self.str = 'spam'
    dumps   = lambda self: repr(self)
    __str__ = lambda self: self.dumps()

data = Data()
print data

Sem argumentos:

$ python dump.py
<__main__.Data instance at 0x00A052D8>

Com o Gnosis Utils :

$ python dump.py gnosis.magic MetaXMLPickler
<?xml version="1.0"?>
<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
<PyObject module="__main__" class="Data" id="11038416">
<attr name="lst" type="list" id="11196136" >
  <item type="string" value="a" />
  <item type="string" value="b" />
  <item type="string" value="c" />
</attr>
<attr name="num" type="numeric" value="38" />
<attr name="str" type="string" value="spam" />
</PyObject>

Está um pouco desatualizado, mas ainda está funcionando.


6

Se você está usando isso para depuração e deseja apenas um despejo recursivo de tudo, a resposta aceita é insatisfatória porque exige que suas classes já tenham boas __str__implementações. Se não for esse o caso, isso funciona muito melhor:

import json
print(json.dumps(YOUR_OBJECT, 
                 default=lambda obj: vars(obj),
                 indent=1))

Isto não funcionou em python 3. tive que instalar pymongo e fazê-lo de acordo com a resposta de @Clark
Tim Ogilvy

Tal como acontece com muitas das outras respostas aquiTypeError: vars() argument must have __dict__ attribute
Rob

6

Tente ppretty

from ppretty import ppretty


class A(object):
    s = 5

    def __init__(self):
        self._p = 8

    @property
    def foo(self):
        return range(10)


print ppretty(A(), show_protected=True, show_static=True, show_properties=True)

Resultado:

__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)

exatamente o que eu estava procurando para depuração rápida :), ótima descoberta!
Joseph Astrahan

pouca dica adicione profundidade = 6 (ou o quanto você precisar) como um dos parâmetros e os detalhes da recursão podem ir além :). Uma das coisas que eu mais gosto na impressão de listas é que mostra as 2 primeiras entradas e as 2 últimas entradas para que você saiba que está funcionando
Joseph Astrahan

4
from pprint import pprint

def print_r(the_object):
    print ("CLASS: ", the_object.__class__.__name__, " (BASE CLASS: ", the_object.__class__.__bases__,")")
    pprint(vars(the_object))

4

Isso imprime todo o conteúdo do objeto recursivamente no formato indentado json ou yaml:

import jsonpickle # pip install jsonpickle
import json
import yaml # pip install pyyaml

serialized = jsonpickle.encode(obj, max_depth=2) # max_depth is optional
print json.dumps(json.loads(serialized), indent=4)
print yaml.dump(yaml.load(serialized), indent=4)

4

Votou a resposta que menciona apenas pprint. Para ser claro, se você deseja ver todos os valores em uma estrutura de dados complexa, faça algo como:

from pprint import pprint
pprint(my_var)

Onde my_var é sua variável de interesse. Quando usei, pprint(vars(my_var))não obtive nada e as outras respostas aqui não ajudaram ou o método pareceu desnecessariamente longo. A propósito, no meu caso particular, o código que eu estava inspecionando tinha um dicionário de dicionários.

Vale ressaltar que, com algumas classes personalizadas, você pode acabar tendo um <someobject.ExampleClass object at 0x7f739267f400>tipo de saída inútil . Nesse caso, talvez você precise implementar um __str__método ou tentar algumas das outras soluções. Ainda gostaria de encontrar algo simples que funcione em todos os cenários, sem bibliotecas de terceiros.


3
> com algumas classes personalizadas ... É por isso que não sou fã de python. As coisas "às vezes" funcionam e "às vezes" não
AlxVallejo

3

Eu estava precisando imprimir as informações de DEBUG em alguns logs e não consegui usar o pprint, pois isso iria quebrá-lo. Em vez disso, fiz isso e consegui praticamente a mesma coisa.

DO = DemoObject()

itemDir = DO.__dict__

for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])

3

Para despejar "myObject":

from bson import json_util
import json

print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))

Eu tentei vars () e dir (); ambos falharam pelo que eu estava procurando. vars () não funcionou porque o objeto não tinha __dict__ (exceptions.TypeError: o argumento vars () deve ter o atributo __dict__). dir () não era o que eu estava procurando: é apenas uma lista de nomes de campos, não fornece os valores ou a estrutura do objeto.

Eu acho que json.dumps () funcionaria para a maioria dos objetos sem o padrão = json_util.default, mas eu tinha um campo datetime no objeto para que o serializador json padrão falhasse. Consulte Como superar "datetime.datetime não JSON serializable" em python?


Ok, sim, tive que instalar o pymongo tho para usá-lo.
Tim Ogilvy

3

Por que não algo simples:

for key,value in obj.__dict__.iteritems():
    print key,value

Não deveria ser for key,value in obj.__dict__.iteritems(): print key,value?
Raz

2

O pprint contém uma "impressora bonita" para produzir representações esteticamente agradáveis ​​de suas estruturas de dados. O formatador produz representações de estruturas de dados que podem ser analisadas corretamente pelo intérprete e também são fáceis para o ser humano ler. A saída é mantida em uma única linha, se possível, e recuada quando dividida em várias linhas.


2

Apenas tente impressão .

Isso o ajudará não apenas com a impressão de variáveis ​​de objetos, mas também com uma saída bonita, como esta:

class(NormalClassNewStyle):
  dicts: {
  },
  lists: [],
  static_props: 1,
  tupl: (1, 2)

1
Este módulo não parecia mais ser mantido e possui vários problemas em aberto. Em vez disso, use ppretty
Wavesailor 14/02/19

1

Para todo mundo lutando com

  • vars() não retornando todos os atributos.
  • dir() não retornando os valores dos atributos.

O código a seguir imprime todos os atributos de objcom seus valores:

for attr in dir(obj):
        try:
            print("obj.{} = {}".format(attr, getattr(obj, attr)))
        except AttributeError:
            print("obj.{} = ?".format(attr))

obter nenhum erro, mas não recursivo assim apenas obter uma série de endereços hexadecimais
Rob

0

Você pode tentar a barra de ferramentas Flask Debug.
https://pypi.python.org/pypi/Flask-DebugToolbar

from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)

# the toolbar is only enabled in debug mode:
app.debug = True

# set a 'SECRET_KEY' to enable the Flask session cookies
app.config['SECRET_KEY'] = '<replace with a secret key>'

toolbar = DebugToolbarExtension(app)

0

Eu gosto de trabalhar com chaves ou valores internos de tipos de objetos python .

Para atributos, independentemente de serem métodos ou variáveis:

o.keys()

Para valores desses atributos:

o.values()

0

Isso funciona, independentemente de como suas variáveis ​​sejam definidas dentro de uma classe, dentro de __init__ ou fora.

your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
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.