Відповіді:
Ви дійсно змішуєте дві різні речі.
Використовуйте 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__'}
print re.compile(r'slots').search('No slots here either.').__slots__
inspect
у вашій відповіді більше не поговорити про модуль? Я думаю, що це найближче до print_r або var_dump.
dir()
? dir()
повертає лише список імен, і не всі вони існують в атрибуті vars()
або в ньому __dict__
.
Ви хочете vars()
змішатись із pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
просто повертає __dict__
свій аргумент, і це також є резервом, dir()
якщо немає __dir__
методу. тому використовуйте dir()
в першу чергу, як я вже сказав.
dir()
дає вам все вбудоване в речі, які вам, мабуть, не цікаві, як __str__
і __new__
. var()
не робить.
__dict__
атрибутів.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Існує багато функцій сторонніх виробників, які додають такі речі, як обробка виключень, національне / спеціальне друкування символів, повторне внесення вкладених об'єктів тощо відповідно до уподобань їхніх авторів. Але всі вони зводяться до цього.
getmembers()
функцію в стандартному inspect
модулі, але я подумав, що це буде корисніше, оскільки вона ілюструє, як робити самоаналіз загалом.
__dict__
(наприклад, __doc__
та __module__
). Крім того, __dict__
взагалі не працює для об'єктів, декларованих з __slots__
. Загалом, __dict__
показує властивості рівня користувача, які фактично зберігаються у словнику всередині країни. dir () показує більше.
__dict__
атрибутів / членів. Я знаю, що це божевільно, але правда. Вбудовані модулі , як int
і str
чи re.MatchObject
з є загальними прикладами. Спробуйте 'hello'.__dict__
, тоді спробуйтеdir('hello')
dir був згаданий, але це дасть вам лише імена атрибутів. Якщо ви хочете, щоб їх значення також спробуйте __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Ось вихід:
>>> o.__dict__
{'value': 3}
set
немає __dict__
, тож для них це вийде з ладуAttributeError: 'set' object has no attribute '__dict__'
Для цього можна скористатися функцією "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
Для друку поточного стану об'єкта ви можете:
>>> 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()
вбудованої функції та оператора друку для обчислення "неформального" рядкового подання об'єкта. Це відрізняється__repr__()
тим, що воно не повинно бути дійсним виразом Python: замість цього може використовуватися більш зручне або стисле подання. Повернене значення повинно бути об’єктом рядка.
print "DEBUG: object value: " + repr(obj)
Можливо, варто перевірити -
Чи існує Python, еквівалентний Дані Perl :: Дампер?
Моя рекомендація така -
https://gist.github.com/1071857
Зауважте, що в perl є модуль під назвою Data :: Dumper, який переводить дані об’єкта назад у вихідний код perl (Примітка: він НЕ переводить код назад у джерело, і майже завжди ви не хочете, щоб функції об'єктних методів у висновку). Це можна використовувати для наполегливості, але загальною метою є налагодження.
Існує ряд речей, яких стандартний pprint python не вдається досягти, зокрема, він просто припиняє спадати, коли бачить екземпляр об'єкта і дає вам внутрішній шістнадцятковий вказівник об'єкта (помилково, цей вказівник не є цілою великою користю шлях). Тож у двох словах, python - це вся ця велика об'єктно-орієнтована парадигма, але інструменти, які ви вийдете з коробки, призначені для роботи з чимось, крім предметів.
Perl Data :: Dumper дозволяє контролювати, наскільки глибоко ви хочете пройти, а також виявляє кругові пов'язані структури (це дійсно важливо). Цей процес принципово простіше досягти в перл, оскільки об'єкти не мають особливої магії поза їх благом (загальновизнаний процес).
Я рекомендую використовувати 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__.
У більшості випадків ви користуєтесь інформацією, яку ви хочете , __dict__
або dir()
отримаєте її. Якщо вам знадобиться більше деталей, стандартна бібліотека включає модуль перевірки , який дозволяє отримати вражаючу кількість деталей. Деякі з реальних помилок інформації включають:
Якщо ви просто шукаєте «що значення атрибутів у мого об'єкта є?», То dir()
і __dict__
, ймовірно , досить. Якщо ви дійсно хочете зануритися в поточний стан довільних об'єктів (маючи на увазі, що в python майже все є об'єктом), тоді inspect
це варто врахувати.
Чи є вбудована функція для друку всіх поточних властивостей та значень об’єкта?
Ні. Найбільш схвалена відповідь виключає деякі види атрибутів, і прийнята відповідь показує, як отримати всі атрибути, включаючи методи та частини непублічних 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__
об'єкт, а це не копія, тож якщо ви модифікуєте дікт, повернений 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
. Але дуже корисно - дякую!
Приклад метапрограмування Скидання об'єкта магією :
$ 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 :
$ 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>
Це трохи застаріло, але все ще працює.
Якщо ви використовуєте це для налагодження, і ви просто хочете рекурсивного скидання всього, прийнята відповідь незадовільна, оскільки це вимагає, щоб ваші класи вже мали хороші __str__
реалізації. Якщо це не так, це працює набагато краще:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
Спробуйте 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)
Це виводить весь вміст об'єкта рекурсивно у форматі 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)
Я підтримав відповідь, що згадує лише pprint. Щоб було зрозуміло, якщо ви хочете бачити всі значення в складному структурі даних, тоді зробіть щось на кшталт:
from pprint import pprint
pprint(my_var)
Там, де мій_вар - ваша змінна особа . Коли я використав, pprint(vars(my_var))
я нічого не отримав, а інші відповіді тут не допомогли, або метод виглядав надмірно довго. До речі, в моєму конкретному випадку код, який я перевіряв, мав словник словників.
Варто зазначити, що з деякими спеціальними класами ви можете просто закінчитись із недоброзичливим <someobject.ExampleClass object at 0x7f739267f400>
видом. У такому випадку вам, можливо, доведеться реалізувати __str__
метод або спробувати деякі інші рішення. Я все одно хотів би знайти щось просте, яке працює у всіх сценаріях, без сторонніх бібліотек.
Щоб скинути "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__ (виключення.TypeError: аргумент vars () повинен мати атрибут __dict__). dir () - це не те, що я шукав: це лише перелік імен полів, не дає значень чи структури об'єкта.
Я думаю, що json.dumps () буде працювати для більшості об'єктів без типового = json_util.default, але у мене було поле дати в об’єкті, тому стандартний серіалізатор json не вдався. Див. Як подолати "datetime.datetime не JSON serializable" у python?
Чому б не щось просте:
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
?
pprint містить «гарний принтер» для створення естетичних зображень вашої структури даних. Форматор створює уявлення про структуру даних, які можна правильно проаналізувати інтерпретатором, а також легко читати людині. Якщо можливо, висновок зберігається в одному рядку і відступається при розділенні на кілька рядків.
Просто спробуйте звуковий сигнал .
Це допоможе вам не тільки з друком змінних об'єктів, але і з прекрасним виведенням, як це:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Для всіх, хто бореться
vars()
не повертаючи всіх атрибутів. dir()
не повертає значення атрибутів.Наступний код друкує всі атрибути obj
з їх значеннями:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Ви можете спробувати панель інструментів налагодження 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)
__dict__
члена (re.MatchObject
наприклад,), але вбудованийdir()
працює для всіх об'єктів.