Рекурсивно сбрасывать объект
Я не уверен, есть ли стандартный способ сделать это. Я выполнил следующую функцию для сброса всего содержимого объекта. Он должен рекурсивно выгружать под-объекты, поэтому я проверяю InstanceType
, но он не работает:
import types
def dump_obj(obj, level=0):
for a in dir(obj):
try:
if type(obj.__dict__[a]) == types.InstanceType:
dump_obj(obj.__dict__[a], level + 2)
else:
try:
print " " * level + "%s -> %s" % (a, obj.__dict__[a])
except:
pass
except:
pass
Как проверить, является ли элемент самим объектом?
То, что я действительно хочу, это следующее. Дано:
class B:
def __init__(self):
self.txt = 'bye'
class A:
def __init__(self):
self.txt = 'hello'
self.b = B()
a = A()
dump_obj(a)
Мне нужен следующий вывод:
txt -> hello
txt -> bye
Ответы
Ответ 1
Всегда лучше использовать isinstance(x, y)
вместо type(x) == y
.
Поскольку в Python все является объектом, делать это не имеет смысла isinstance(attr, object)
, потому что (я думаю) он всегда возвращает true.
Лучше всего "черный список" определенных типов. Например, вы проверяете, идет ли он дальше, чем int, float, str, unicode, list, dict, set, ...
, в противном случае вы просто печатаете его.
Например:
def dump(obj, level=0):
for a in dir(obj):
val = getattr(obj, a)
if isinstance(val, (int, float, str, unicode, list, dict, set)):
print level*' ', val
else:
dump(val, level=level+1)
UPDATE: isinstance
учитывает наследование, поэтому, если вы попытаетесь увидеть, является ли объект экземпляром родительского класса, он вернет True, а может и нет при использовании типа.
Поскольку в этом случае вы будете тестировать примитивные типы, в этом случае это может не иметь никакого значения, но в целом isinstance
предпочтительнее.
Посмотрите этот пример:
>>> class A(object): pass
...
>>> class B(A): pass
...
>>> a, b = A(), B()
>>> type(a)
<class '__main__.A'>
>>> type(a) == A
True
>>> type(b)
<class '__main__.B'>
>>> type(b) == B
True
>>> type(b) == A
False
>>>
Вы можете проверить документы
Ответ 2
Это рекурсивно сбросит любой объект и все подобъекты. Другие ответы работали для простых примеров, но для сложных объектов им не хватало некоторых данных.
import jsonpickle # pip install jsonpickle
import json
serialized = jsonpickle.encode(obj)
print(json.dumps(json.loads(serialized), indent=2))
ОБНОВЛЕНИЕ: если вы используете формат YAML, он будет еще ближе к вашему примеру.
import yaml # pip install pyyaml
print(yaml.dump(yaml.load(serialized), indent=2))
Ответ 3
Ваш код работает для меня, за исключением того, что вещи печатаются в неправильном порядке (сначала во-первых, что я бы ожидал с рекурсией).
Итак, я изменил порядок (и использовал isinstance()
, а также итерацию по __dict__
):
import types
def dump_obj(obj, level=0):
for key, value in obj.__dict__.items():
if not isinstance(value, types.InstanceType):
print " " * level + "%s -> %s" % (key, value)
else:
dump_obj(value, level + 2)
class B:
def __init__ (self):
self.txt = 'bye'
class A:
def __init__(self):
self.txt = 'hello'
self.b = B()
a = A()
dump_obj(a)
производит
txt -> hello
txt -> bye