Есть ли встроенная функция для печати всех текущих свойств и значений объекта?

Ответы:

591

Вы действительно смешиваете две разные вещи.

Используйте dir(), vars()или inspectмодуль , чтобы получить то , что вы заинтересованы в том, (я использую в __builtins__качестве примера, вы можете использовать любой объект , а).

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

Распечатайте этот словарь так, как вам нравится:

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

или

>>> 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',
...

Красивая печать также доступна в интерактивном отладчике в виде команды:

(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
Удивительно, но кажется, что не все объекты имеют __dict__члена ( re.MatchObjectнапример), но встроенные функции dir()работают для всех объектов.
вар
print re.compile(r'slots').search('No slots here either.').__slots__
вар
3
Новый для меня. Спасибо. Точка запустила синтаксический анализатор пути моего мозга. Никогда даже не рассматривал латинский «модуль».
конопля
4
почему вы не говорите больше о inspectмодуле в своем ответе? Я думаю, что это самая близкая вещь к print_r или var_dump.
Хай Phaikawl
1
Как вы получаете доступ к значениям атрибутов, перечисленных dir(), тогда? dir()возвращает только список имен, и не все из них существуют в vars()или в __dict__атрибуте.
Hellogoodbye
981

Вы хотите vars()смешать с pprint():

from pprint import pprint
pprint(vars(your_object))
Джереми Кантрелл
источник
24
vars()просто возвращает __dict__свой аргумент, и это также запасной вариант, dir()если нет __dir__метода. так что используйте dir()в первую очередь, как я уже сказал.
28
@hop: dir()дает вам все встроенные в вещи , которые вы , вероятно , не заботятся о том, как __str__и __new__. var()не делает.
Тимммм
14
Это терпит неудачу на наборах и других объектах, у которых нет __dict__атрибута.
анатолий техтоник
209
def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

Существует множество сторонних функций, которые добавляют такие вещи, как обработка исключений, печать национальных / специальных символов, повторное использование вложенных объектов и т. Д. В соответствии с предпочтениями их авторов. Но все они в основном сводятся к этому.

Дэн Ленски
источник
5
unpythonic, потому что следует не изобретено здесь
14
Чего-чего? Конечно, вы можете использовать getmembers()функцию в стандартном inspectмодуле, но я подумал, что это было бы более полезно, поскольку оно иллюстрирует, как сделать самоанализ в целом.
Дэн Ленски
20
НЕ ЗА ЧТО. dir (obj) показывает свойства, которые не найдены в __dict__(такие как __doc__и __module__). Кроме того, __dict__совсем не работает для объектов, объявленных с __slots__. В общем, __dict__показывает пользовательские свойства, которые на самом деле хранятся в словаре внутри. dir () показывает больше.
Дэн Ленски
8
Некоторые классы / объекты не содержат никаких __dict__атрибутов / членов. Я знаю, что это безумие, но это правда. Встроенные модули, такие как intand strили re.MatchObjects, являются типичными примерами. Попробуй 'hello'.__dict__, потом попробуйdir('hello')
конфорки
11
Мне все равно, будь это «пифон» или еще много чего. Он выполняет свою работу, что при отладке - единственное, что имеет значение.
hidefromkgb
59

dir был упомянут, но это даст вам только имена атрибутов. Если вы хотите их значения, попробуйте __dict__.

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

o = O()

Вот вывод:

>>> o.__dict__

{'value': 3}
eduffy
источник
9
Такие объекты, как setне имеет __dict__, поэтому для них это не удастсяAttributeError: 'set' object has no attribute '__dict__'
Анатолий Techtonik
23

Вы можете использовать функцию "dir ()", чтобы сделать это.

>>> 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']
>>>

Еще одна полезная функция - помощь.

>>> 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

Чтобы напечатать текущее состояние объекта, вы можете:

>>> obj # in an interpreter

или

print repr(obj) # in a script

или

print obj

Для ваших занятий определите __str__или __repr__методы. Из документации Python :

__repr__(self)Вызывается repr()встроенной функцией и преобразованиями строк (обратными кавычками) для вычисления «официального» строкового представления объекта. Если это вообще возможно, это должно выглядеть как допустимое выражение Python, которое можно использовать для воссоздания объекта с тем же значением (с учетом соответствующей среды). Если это невозможно, должна быть возвращена строка вида "<... некоторое полезное описание ...>". Возвращаемое значение должно быть строковым объектом. Если класс определяет repr (), но нет __str__(), тогда __repr__()он также используется, когда требуется «неформальное» строковое представление экземпляров этого класса. Обычно это используется для отладки, поэтому важно, чтобы представление было насыщенным информацией и однозначным.

__str__(self)Вызывается str()встроенной функцией и оператором print для вычисления «неформального» строкового представления объекта. Это отличается от того, __repr__()что оно не обязательно должно быть допустимым выражением Python: вместо него можно использовать более удобное или краткое представление. Возвращаемое значение должно быть строковым объектом.

JFS
источник
Эта опция полезна для печати строк, объединенных с содержимым объекта:print "DEBUG: object value: " + repr(obj)
AlejandroVD
17

Может стоит проверить -

Есть ли Python эквивалентный Perl Data :: Dumper?

Моя рекомендация такая -

https://gist.github.com/1071857

Обратите внимание, что в perl есть модуль Data :: Dumper, который переводит данные объекта обратно в исходный код perl (примечание: он НЕ переводит код обратно в исходный код, и почти всегда вам не нужны функции метода объекта в выходных данных). Это может использоваться для постоянства, но общая цель для отладки.

Есть ряд вещей, которые не удается выполнить стандартному python pprint, в частности он просто останавливается, когда видит экземпляр объекта, и выдает внутренний шестнадцатеричный указатель объекта (ошибочно, этот указатель не очень полезен путь). Итак, в двух словах, Python - это все об этой великолепной объектно-ориентированной парадигме, но инструменты, которые вы получаете из коробки, предназначены для работы с чем-то, кроме объектов.

Perl Data :: Dumper позволяет вам контролировать, насколько глубоко вы хотите зайти, а также обнаруживает циклически связанные структуры (это действительно важно). Этот процесс принципиально проще осуществить в Perl, потому что у объектов нет особой магии, кроме их благословения (универсально четко определенный процесс).

телефон
источник
Это должно быть пип и деб не только суть!
фоб
2
> Итак, в двух словах, Python - это все об этой великолепной объектно-ориентированной парадигме, но инструменты, которые вы получаете из коробки, предназначены для работы с чем-то, кроме объектов ... Довольно претензия, когда единственный пример, который вы предоставляете, это модуль второстепенной важности.
Мемеплекс
@memeplex, где написано, что python это все о ООП?
Питер Вуд
Хорошо, это просто говорит, что это все об этом великолепном ООП, мой плохой.
memeplex
13

Я рекомендую использовать 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__.
прости
источник
О, мужик, +100500
Кирби
12

В большинстве случаев, используя __dict__ или dir()вы получите необходимую информацию. Если вам нужно больше подробностей, стандартная библиотека включает в себя модуль проверки , который позволяет получить впечатляющее количество деталей. Некоторые из реальных кусочков информации включают в себя:

  • имена параметров функций и методов
  • иерархии классов
  • Исходный код реализации функций / классов объектов
  • локальные переменные вне объекта кадра

Если вы просто ищете «какие значения атрибутов имеет мой объект?», То dir()и __dict__, вероятно, достаточно. Если вы действительно хотите заглянуть в текущее состояние произвольных объектов (имея в виду, что в python почти все является объектом), то inspectстоит рассмотреть.

Уильям МакВей
источник
Воспользовался вашим объяснением на осмотре, чтобы улучшить наиболее полный ответ. Надеюсь, с тобой все в порядке.
Фернандо Сезар
10

Есть ли встроенная функция для печати всех текущих свойств и значений объекта?

Нет. Ответ с наибольшим количеством голосов исключает некоторые виды атрибутов, и принятый ответ показывает, как получить все атрибуты, включая методы и части закрытого API. Но нет хорошего полного встроенного функции.

Таким образом, короткое следствие заключается в том, что вы можете написать свой собственный, но он будет вычислять свойства и другие вычисляемые дескрипторы данных, которые являются частью общедоступного API, и вы можете этого не захотеть:

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))

Проблемы с другими ответами

Обратите внимание на применение ответа, получившего наибольшее количество голосов в классе с множеством различных типов данных:

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))

только отпечатки:

{'baz': 'baz'}

Потому что возвращает vars только__dict__ объект, и это не копия, поэтому, если вы изменяете dict, возвращаемый vars, вы также изменяете __dict__сам объект.

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

возвращает:

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

- что плохо, потому что quux - это свойство, которое мы не должны устанавливать и не должны находиться в пространстве имен ...

Применение совета в принятом в настоящее время ответе (и других) не намного лучше:

>>> 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']

Как мы видим, dirвозвращает только все (на самом деле только большинство) из имен, связанных с объектом.

inspect.getmembersУпоминается в комментариях, также имеет недостатки - возвращает все имена и значения.

Из класса

При обучении мои ученики создают функцию, которая предоставляет семантически открытый API объекта:

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

Мы можем расширить это, чтобы предоставить копию семантического пространства имен объекта, но нам нужно исключить __slots__те, которые не назначены, и, если мы серьезно относимся к запросу «текущих свойств», нам нужно исключить вычисляемые свойства (так как они могут стать дорогими и могут быть истолкованы как не «текущие»):

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)}

И теперь мы не рассчитываем и не показываем свойство quux:

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

Предостережения

Но, возможно, мы знаем, что наша недвижимость не дорогая. Мы можем захотеть изменить логику, чтобы включить их. И, возможно, мы хотим исключить другие пользовательские дескрипторы данных.

Затем нам нужно дополнительно настроить эту функцию. И поэтому имеет смысл, что у нас не может быть встроенной функции, которая волшебным образом точно знает, чего мы хотим, и обеспечивает ее. Это функциональность, которую мы должны создать сами.

Вывод

Нет встроенной функции, которая делает это, и вы должны делать то, что наиболее семантически подходит для вашей ситуации.

Аарон Холл
источник
Есть дополнительная тесная скобка после FunctionType. Но очень полезно - спасибо!
nealmcb
@nealmcb спасибо, я думаю, что понял. Рад помочь! :)
Аарон Холл
7

Пример метапрограммирования Dump объект с магией :

$ 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

Без аргументов:

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

С 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>

Это немного устарело, но все еще работает.

JFS
источник
6

Если вы используете это для отладки и просто хотите получить рекурсивный дамп всего, принятый ответ неудовлетворителен, поскольку требует, чтобы у ваших классов уже были хорошие __str__реализации. Если это не так, это работает намного лучше:

import json
print(json.dumps(YOUR_OBJECT, 
                 default=lambda obj: vars(obj),
                 indent=1))
Адам Кэт
источник
это не работало на питоне 3. Пришлось установить pymongo и сделать это согласно ответу @Clark
Тим Огилви
как и многие другие ответы здесьTypeError: vars() argument must have __dict__ attribute
ограбить
6

Попробуйте 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)

Вывод:

__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Сымон
источник
именно то, что я искал для быстрой отладки :), отличная находка!
Джозеф Астрахань
Небольшой совет: добавьте глубину = 6 (или как вам нужно) в качестве одного из параметров для этого, и детали рекурсии могут пойти дальше :). Одна из вещей, которые мне нравятся в том, как он печатает списки, это то, что он показывает первые 2 записи и последние 2 записи, чтобы вы знали, что это работает
Джозеф Астрахан
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))
32ndghost
источник
4

Это распечатывает все содержимое объекта рекурсивно в формате с отступом json или 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)
wisbucky
источник
4

Я проголосовал за ответ, который упоминает только pprint. Для ясности, если вы хотите увидеть все значения в сложной структуре данных, сделайте что-то вроде:

from pprint import pprint
pprint(my_var)

Где my_var - ваша переменная интереса. Когда я использовал, pprint(vars(my_var))я ничего не получил, и другие ответы здесь не помогли, или метод выглядел излишне длинным. Кстати, в моем конкретном случае проверяемый код содержал словарь словарей.

Стоит отметить, что с некоторыми пользовательскими классами вы можете просто получить бесполезный <someobject.ExampleClass object at 0x7f739267f400>вид вывода. В этом случае вам может понадобиться реализовать __str__метод или попробовать другие решения. Я все еще хотел бы найти что-то простое, которое работает во всех сценариях, без сторонних библиотек.

Nagev
источник
3
> с некоторыми пользовательскими классами ... Вот почему я не фанат питона. Вещи «иногда» работают, а «иногда» нет
AlxVallejo
3

Мне нужно было распечатать информацию отладки в некоторых журналах и не смог использовать pprint, потому что это сломало бы ее. Вместо этого я сделал это и получил практически то же самое.

DO = DemoObject()

itemDir = DO.__dict__

for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])
DaOneTwo
источник
3

Чтобы создать дамп myObject:

from bson import json_util
import json

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

Я пробовал vars () и dir (); оба потерпели неудачу из-за того, что я искал. vars () не работал, потому что у объекта не было __dict__ (exceptions.TypeError: аргумент vars () должен иметь атрибут __dict__). dir () не то, что я искал: это просто список имен полей, не дает значений или структуру объекта.

Я думаю, что json.dumps () будет работать для большинства объектов без default = json_util.default, но у меня было поле datetime в объекте, поэтому стандартный сериализатор json не сработал. Смотрите Как преодолеть «datetime.datetime, не JSON serializable» в python?

Кларк
источник
Хорошо, да, пришлось использовать Pymongo Tho, чтобы использовать его.
Тим Огилви
3

Почему не что-то простое:

for key,value in obj.__dict__.iteritems():
    print key,value
Майкл Тамм
источник
Не должно ли это быть for key,value in obj.__dict__.iteritems(): print key,value?
Раз
2

pprint содержит «симпатичный принтер» для создания эстетически приятных представлений о ваших структурах данных. Форматировщик создает представления структур данных, которые могут быть правильно проанализированы интерпретатором, и которые также легко читаются человеком. Выходные данные хранятся в одной строке, если это возможно, и имеют отступ, если разделены на несколько строк.

shahjapan
источник
2

Просто попробуйте beeprint .

Это поможет вам не только с печатью переменных объекта, но и с красивым выводом, например так:

class(NormalClassNewStyle):
  dicts: {
  },
  lists: [],
  static_props: 1,
  tupl: (1, 2)
Аньяны Пан
источник
1
Этот модуль, похоже, больше не поддерживается и имеет ряд открытых вопросов. Скорее используйте ppretty
Wavesailor
1

Для всех, кто борется с

  • vars() не возвращает все атрибуты.
  • dir() не возвращает значения атрибутов.

Следующий код печатает все атрибуты objс их значениями:

for attr in dir(obj):
        try:
            print("obj.{} = {}".format(attr, getattr(obj, attr)))
        except AttributeError:
            print("obj.{} = ?".format(attr))
Роберт Хениг
источник
не получаю ошибки, но не рекурсивные так просто получить много шестигранных адресов
грабят
0

Вы можете попробовать панель инструментов отладки Flask.
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)
Slipstream
источник
0

Мне нравится работать с ключами или значениями встроенных типов объектов Python .

Для атрибутов независимо от того, являются ли они методами или переменными:

o.keys()

Для значений этих атрибутов:

o.values()
Evhz
источник
0

Это работает независимо от того, как ваши переменные определены в классе, внутри __init__ или снаружи.

your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
Карл Чунг
источник