Форматирование словаря Python

Я сделал функцию python для преобразования словарей в форматированные строки. Моя цель состояла в том, чтобы функция взяла словарь для ввода и превратила его в строку, которая выглядела хорошо. Например, что-то вроде «{'text': 'Hello', 'blah': {'hi': 'hello', 'hello': 'hi'}}" будет превращено в это:

 текст:
     Здравствуйте
 л:
     Здравствуй:
         Здравствуйте
     Здравствуйте:
         Здравствуй

Это код, который я написал:

indent = 0 def format_dict(d): global indent res = "" for key in d: res += (" " * indent) + key + ":\n" if not type(d[key]) == type({}): res += (" " * (indent + 1)) + d[key] + "\n" else: indent += 1 res += format_dict(d[key]) indent -= 1 return res #test print format_dict({'key with text content':'some text', 'key with dict content': {'cheese': 'text', 'item':{'Blah': 'Hello'}}}) 

Отлично работает. Он проверяет, является ли элемент словаря другим словарем, в котором он обрабатывает это, или что-то еще, в котором он будет использовать это значение. Проблема в том, что я не могу иметь словарь и строку вместе в словаре. Например: если бы я хотел

 л:
     Здравствуй
     Здравствуйте:
         и снова здравствуйте

не было бы никакого способа сделать это. Есть ли способ, которым я мог бы иметь что-то вроде элемента списка в словаре. Что-то вроде этого "{'blah': {'hi', 'hello': 'hello again'}}"? И если вы предоставите решение, можете ли вы рассказать мне, как мне нужно будет изменить свой код (если он потребует изменений).
Примечание . Я использую python 2.5

Вы можете просто сохранить список в словаре. Кроме того, лучше не использовать глобальное хранилище для отпечатка. Что-то вроде:

 def format_value(v, indent): if isinstance(v, list): return ''.join([format_value(item, indent) for item in v]) elif isinstance(v, dict): return format_dict(v, indent) elif isinstance(v, str): return (" " * indent) + v + "\n" def format_dict(d, indent=0): res = "" for key in d: res += (" " * indent) + key + ":\n" res += format_value(d[key], indent + 1) return res 

Вы можете выразить словари как имеющие списки детей:

 {'blah': [ 'hi', {'hello':[ 'hello again' ]}, {'goodbye':[ 'hasta la vista, baby' ]} ]} 

Следствием этого является то, что каждый словарь будет иметь только одну пару ключ-значение. С положительной стороны это означает, что вы можете повторять ключи и детерминированный порядок, точно так же, как XML.

EDIT: С другой стороны, вы могли бы просто сбросить 'hello' и 'goodbye' в один словарь, хотя я лично считаю, что это довольно запутанно, так как теперь у вас может быть беспорядочное упорядоченное и неупорядоченное. Поэтому я предполагаю, что правило с одним ключом для словаря является скорее рекомендацией, чем требованием.

Почему бы просто не использовать yaml ?

 import yaml import StringIO d = {'key with text content':'some text', 'key with dict content': {'cheese': 'text', 'item': {'Blah': 'Hello'}}} s = StringIO.StringIO() yaml.dump(d, s) print s.getvalue() 

это печатает:

 key with dict content: cheese: text item: {Blah: Hello} key with text content: some text 

и вы можете загрузить его обратно в dict

 s.seek(0) d = yaml.load(s) 

Словарь – это сопоставление, поэтому вы не можете иметь ключ без значения. Тем не менее, наиболее близким к этому было бы ключом, чтобы иметь значение None . Затем добавьте проверку для None перед строкой if not type(d[key]) == type({}): и continue избегать печати значения. Кстати, эта строка была бы лучше, if not isinstance(d[key], dict):

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

 # -*- coding: utf-8 -*- #!/usr/bin/env python2.5 # http://stackoverflow.com/questions/2748378/python-dictionary-formating def pretty_dict(d, indent=0, spacer='.'): """ takes a dict {'text':'Hello', 'blah':{'hi':'hello','hello':'hi'}} And prints: text: Hello blah: hi: hello hello: hi """ kindent = spacer * indent if isinstance(d, basestring): return kindent + d if isinstance(d, list): return '\n'.join([(pretty_dict(v, indent, spacer)) for v in d]) return '\n'.join(['%s%s:\n%s' % (kindent, k, pretty_dict(v, indent + 1, spacer)) for k, v in d.items()]) test_a = {'text':'Hello', 'blah':{'hi':'hello','hello':'hi'}} test_b = {'key with text content':'some text', 'key with dict content': {'cheese': 'text', 'item':{'Blah': 'Hello'}}} test_c = {'blah':['hi', {'hello':'hello again'}]} test_d = {'blah': [ 'hi', {'hello':[ 'hello again' ]}, {'goodbye':[ 'hasta la vista, baby' ]} ]} if __name__ == '__main__': print pretty_dict(test_a) print pretty_dict(test_b) print pretty_dict(test_c) print pretty_dict(test_d) 

Почему бы не использовать красивую печать, которая уже делает все это?

http://docs.python.org/dev/library/pprint.html