Вот то, что я придумал, прежде чем исследовать и найти этот ответ.На самом деле это хорошо работает для сложных ответов suds, а также для других объектов, таких как __builtins__
, поскольку решение не зависит от suds:
import datetime
def object_to_dict(obj):
if isinstance(obj, (str, unicode, bool, int, long, float, datetime.datetime, datetime.date, datetime.time)):
return obj
data_dict = {}
try:
all_keys = obj.__dict__.keys() # vars(obj).keys()
except AttributeError:
return obj
fields = [k for k in all_keys if not k.startswith('_')]
for field in fields:
val = getattr(obj, field)
if isinstance(val, (list, tuple)):
data_dict[field] = []
for item in val:
data_dict[field].append(object_to_dict(item))
else:
data_dict[field] = object_to_dict(val)
return data_dict
Это решение работает и на самом деле быстрее.Он также работает с объектами, которые не имеют атрибута __keylist__
.
Я 100 раз проводил эталонный тест для выходного объекта со сложной пеной, время выполнения этого решения составляло от 0,04 до 0,052 секунды (в среднем 0,045724287).В то время как recursive_asdict
решение, приведенное выше, выполнялось за 0,082–0,102 секунды, что почти удвоилось (в среднем 0,0829765582).
Затем я вернулся к чертежной доске и повторно выполнил функцию, чтобы получить от нее большую производительность, ион не нуждается в импорте datetime
.Я использовал атрибут __keylist__
, поэтому он не будет работать с другими объектами, такими как __builtins__
, но хорошо работает для вывода объекта suds:
def fastest_object_to_dict(obj):
if not hasattr(obj, '__keylist__'):
return obj
data = {}
fields = obj.__keylist__
for field in fields:
val = getattr(obj, field)
if isinstance(val, list): # tuple not used
data[field] = []
for item in val:
data[field].append(fastest_object_to_dict(item))
else:
data[field] = fastest_object_to_dict(val)
return data
Время выполнения составляло 0,18 - 0,033 секунды (0,0260889721в среднем), поэтому почти в 4 раза быстрее, чем решение recursive_asdict
.