Làm thế nào để in đẹp từ điển lồng nhau?


289

Làm thế nào tôi có thể in một từ điển với độ sâu ~ 4 bằng Python? Tôi đã thử in ấn đẹp pprint(), nhưng nó không hoạt động:

import pprint 
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)

Tôi chỉ đơn giản muốn một vết lõm ( "\t") cho mỗi lần lồng, để tôi có được một cái gì đó như thế này:

key1
    value1
    value2
    key2
       value1
       value2

Vân vân.

Tôi có thể làm cái này như thế nào?


29
"Không làm việc" có nghĩa là gì? Vui lòng xác định chính xác làm thế nào pprint "không hoạt động".
S.Lott

5
Bây giờ tôi đã sử dụng 3 trong số các câu trả lời này (mỗi câu trả lời trong một kịch bản cụ thể): Câu trả lời json của @ Ken là tốt nhưng đôi khi không thành công khi đối tượng không thể được nối tiếp (ném ngoại lệ). nếu câu trả lời json của @ Ken không hoạt động, hãy thử trả lời @ Andy yaml và nó sẽ hoạt động nhưng đầu ra chuỗi ít người đọc hơn một chút. [@ sth's answer] là câu trả lời chung chung nhất (nên hoạt động cho mọi đối tượng và không sử dụng bất kỳ lib nào).
Trevor Boyd Smith

Câu trả lời:


143

Tôi không chắc chính xác bạn muốn định dạng trông như thế nào, nhưng bạn có thể bắt đầu với một chức năng như thế này:

def pretty(d, indent=0):
   for key, value in d.items():
      print('\t' * indent + str(key))
      if isinstance(value, dict):
         pretty(value, indent+1)
      else:
         print('\t' * (indent+1) + str(value))

8
Bạn biết câu trả lời thông thường của @ Ken tốt hơn nhiều so với điều này. Json đã xử lý tất cả mọi thứ và điều này có thể gây ra các lỗi như: UnicodeEncodeError: 'ascii' codec không thể mã hóa ký tự u '\ xf3' ở vị trí 50: thứ tự không nằm trong phạm vi (128)
wonderwhy

Tôi không thể làm cho nó hoạt động với chính tả của giải pháp lồng nhau, vì nó đã cho tôi một UnicodeEncodeError, nó cũng không in khóa chính tả, không đi vào danh sách và bộ dữ liệu và không giữ cú pháp hợp lệ của python.
y.petremann

Câu trả lời này có tác dụng như một cơ duyên đối với tôi, tuy nhiên tôi đã đăng một câu hỏi mới stackoverflow.com/questions/36972225/NH đặt giới hạn cho số lượng giá trị sẽ được in.
gsamaras

Khá tốt. Nếu bạn có các danh sách lồng nhau như trong câu hỏi của OP, bạn cần thêm một số xử lý cho điều đó. Nếu bạn gặp sự cố trong Py2, điều đó có thể khiến nó không thể xử lý Unicode đúng cách mà không có các bản hack như __future__câu trả lời hiện nay đề cập, vì vậy bạn phải sử dụng những vấn đề đó bất cứ khi nào cần (hoặc cập nhật lên 3).
sudo

Điều này làm việc đủ tốt cho tôi: python def pretty(d, indent=0): for key, value in d.items(): if isinstance(value, dict): print(' ' * indent + str(key)) pretty(value, indent+1) else: print(' ' * (indent+1) + f"{key}: {value}")
hum3

500

Suy nghĩ đầu tiên của tôi là trình tuần tự hóa JSON có thể khá tốt trong các từ điển lồng nhau, vì vậy tôi đã gian lận và sử dụng nó:

>>> import json
>>> print json.dumps({'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}},
...                  sort_keys=True, indent=4)
{
    "a": 2,
    "b": {
        "x": 3,
        "y": {
            "t1": 4,
            "t2": 5
        }
    }
}

40
Điều này thật tuyệt, nhưng không in tất cả các từ điển tốt. print json.dumps (myObject .__ dict__, sort_keys = True, indent = 4) #TypeError: <object tại 0x0000000002E6A748> không phải là tuần tự hóa JSON
tponthieux

4
Mặc dù điều này có vẻ hữu ích, nhưng đầu ra của nó không phải là điều OP muốn.
martineau

2
@martineau: Đầu ra được yêu cầu của OP không có ý nghĩa, từ điển cần khóa cho mỗi giá trị.
ness101

2
@ naught101: Một máy in đẹp có thể làm bất cứ điều gì cần thiết để tạo ra đầu ra mong muốn.
martineau

22
json.dumps lấy một hàm chuyển đổi làm đối số tùy chọn, vì vậy với json.dumps (myObject .__ dict__, sort_keys = True, indent = 4, deault = str), ít nhất bạn có thể sử dụng một đối tượng thực hiện repr để tự in
Kiểu

56

Bạn có thể thử YAML qua PyYAML . Đầu ra của nó có thể được tinh chỉnh. Tôi đề nghị bắt đầu với những điều sau đây:

print yaml.dump(data, allow_unicode=True, default_flow_style=False)

Kết quả rất dễ đọc; nó cũng có thể được phân tích cú pháp trở lại Python nếu cần.

Biên tập:

Thí dụ:

>>> import yaml
>>> data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> print yaml.dump(data, default_flow_style=False)
a: 2
b:
  x: 3
  y:
    t1: 4
    t2: 5

1
Sử dụng yaml rất thú vị vì nó giữ kiểu dữ liệu theo định dạng của nó, điều duy nhất tôi có thể nói là nó không tạo ra chuỗi python hợp lệ, nhưng gần như có thể được chuyển đổi lại thành python.
y.petremann

1
yaml không thích phiên bản các loại vô hướng của Numpy ... Tôi không ngạc nhiên rằng nó không hỗ trợ các mảng numpy, nhưng tôi đã mong đợi cùng một đầu ra cho a floatnumpy.float64
PhilMacKay

Cách tiếp cận này cũng hiệu quả với tôi khi sử dụng danh sách từ điển
Grant Shannon

36

Về những gì đã được thực hiện, tôi không thấy bất kỳ máy in đẹp nào ít nhất bắt chước đầu ra của trình thông dịch python với định dạng rất đơn giản nên đây là của tôi:

class Formatter(object):
    def __init__(self):
        self.types = {}
        self.htchar = '\t'
        self.lfchar = '\n'
        self.indent = 0
        self.set_formater(object, self.__class__.format_object)
        self.set_formater(dict, self.__class__.format_dict)
        self.set_formater(list, self.__class__.format_list)
        self.set_formater(tuple, self.__class__.format_tuple)

    def set_formater(self, obj, callback):
        self.types[obj] = callback

    def __call__(self, value, **args):
        for key in args:
            setattr(self, key, args[key])
        formater = self.types[type(value) if type(value) in self.types else object]
        return formater(self, value, self.indent)

    def format_object(self, value, indent):
        return repr(value)

    def format_dict(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + repr(key) + ': ' +
            (self.types[type(value[key]) if type(value[key]) in self.types else object])(self, value[key], indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_list(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_tuple(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + self.lfchar + self.htchar * indent)

Để khởi tạo nó:

pretty = Formatter()

Nó có thể hỗ trợ thêm trình định dạng cho các kiểu đã xác định, bạn chỉ cần tạo một hàm cho kiểu như thế này và liên kết nó với kiểu bạn muốn với set_formater:

from collections import OrderedDict

def format_ordereddict(self, value, indent):
    items = [
        self.lfchar + self.htchar * (indent + 1) +
        "(" + repr(key) + ', ' + (self.types[
            type(value[key]) if type(value[key]) in self.types else object
        ])(self, value[key], indent + 1) + ")"
        for key in value
    ]
    return 'OrderedDict([%s])' % (','.join(items) +
           self.lfchar + self.htchar * indent)
pretty.set_formater(OrderedDict, format_ordereddict)

Vì lý do lịch sử, tôi giữ máy in đẹp trước đó là chức năng thay vì một lớp, nhưng cả hai đều có thể được sử dụng theo cùng một cách, phiên bản lớp chỉ đơn giản là cho phép nhiều hơn:

def pretty(value, htchar='\t', lfchar='\n', indent=0):
    nlch = lfchar + htchar * (indent + 1)
    if type(value) is dict:
        items = [
            nlch + repr(key) + ': ' + pretty(value[key], htchar, lfchar, indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is list:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is tuple:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + lfchar + htchar * indent)
    else:
        return repr(value)

Để dùng nó :

>>> a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':pretty,'unicode':u'\xa7',("tuple","key"):"valid"}
>>> a
{'function': <function pretty at 0x7fdf555809b0>, 'tuple': ('a', 'b', 1, 2), 'list': ['a', 'b', 1, 2], 'dict': {'a': 1, 2: 'b'}, 'unicode': u'\xa7', ('tuple', 'key'): 'valid'}
>>> print(pretty(a))
{
    'function': <function pretty at 0x7fdf555809b0>,
    'tuple': (
        'a',
        'b',
        1,
        2
    ),
    'list': [
        'a',
        'b',
        1,
        2
    ],
    'dict': {
        'a': 1,
        2: 'b'
    },
    'unicode': u'\xa7',
    ('tuple', 'key'): 'valid'
}

So với các phiên bản khác:

  • Giải pháp này tìm kiếm trực tiếp cho loại đối tượng, vì vậy bạn có thể in hầu hết mọi thứ, không chỉ liệt kê hoặc đọc chính tả.
  • Không có bất kỳ sự phụ thuộc.
  • Tất cả mọi thứ được đặt trong một chuỗi, vì vậy bạn có thể làm bất cứ điều gì bạn muốn với nó.
  • Lớp và hàm đã được kiểm tra và hoạt động với Python 2.7 và 3.4.
  • Bạn có thể có tất cả các loại đối tượng bên trong, đây là đại diện của chúng chứ không phải nội dung của chúng được đưa vào kết quả (vì vậy chuỗi có dấu ngoặc kép, chuỗi Unicode được thể hiện đầy đủ ...).
  • Với phiên bản lớp, bạn có thể thêm định dạng cho mọi loại đối tượng bạn muốn hoặc thay đổi chúng cho các loại đã được xác định.
  • khóa có thể là bất kỳ loại hợp lệ.
  • Nhân vật thụt lề và dòng mới có thể được thay đổi cho mọi thứ chúng ta muốn.
  • Dict, List và Tuples được in đẹp.

2
Đây chắc chắn là giải pháp được chấp nhận - việc thiếu sự phụ thuộc vào JSON là rất lớn.
Josh

Sẽ thật tuyệt nếu nó có thể làm các đối tượng bằng cách chuyển đổi chúng thành các ký tự và đặt khóa của chúng thành loại đối tượng
Alex Cory

Về cơ bản, bạn có thể thay thế phương thức format_object internaly hoặc externaly để làm điều đó.
y.petremann

set_formater - cần hai t, đây là một lỗi đánh máy, nên là định dạng
Nikolay Prokopyev

32

bằng cách này, bạn có thể in nó theo cách đẹp, ví dụ như tên từ điển của bạn là yasin

import json

print (json.dumps(yasin, indent=2))

5
Điều này giả định nội dung của từ điển là json serialize-could, điều này nhất thiết không đúng.
SpiXel

8

Một tùy chọn khác với yapf:

from pprint import pformat
from yapf.yapflib.yapf_api import FormatCode

dict_example = {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5], '4': {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5]}}
dict_string = pformat(dict_example)
formatted_code, _ = FormatCode(dict_string)

print(formatted_code)

Đầu ra:

{
    '1': '1',
    '2': '2',
    '3': [1, 2, 3, 4, 5],
    '4': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5]
    }
}

5

Như những người khác đã đăng, bạn có thể sử dụng đệ quy / dfs để in dữ liệu từ điển lồng nhau và gọi đệ quy nếu đó là từ điển; mặt khác in dữ liệu.

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data

5

Một trong những cách pythonic nhất cho điều đó là sử dụng mô-đun pprint đã được xây dựng .

Đối số mà bạn cần để xác định độ sâu in là như bạn mong đợi depth

import pprint
pp = pprint.PrettyPrinter(depth=4)
pp.pprint(mydict)

Đó là nó !


4

bĩu môi có thể in bất cứ thứ gì bạn ném vào nó, ví dụ (mượn datatừ câu trả lời khác):

data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)

sẽ dẫn đến kết quả đầu ra được in ra màn hình như:

{
    'a': 2,
    'b':
    {
        'y':
        {
            't2': 5,
            't1': 4
        },
        'x': 3
    }
}

hoặc bạn có thể trả về đầu ra chuỗi được định dạng của đối tượng của bạn:

v = pout.s(data)

Trường hợp sử dụng chính của nó là để gỡ lỗi để nó không bị sặc trên các đối tượng hoặc bất cứ thứ gì và nó xử lý đầu ra unicode như bạn mong đợi, hoạt động trong python 2.7 và 3.

tiết lộ : Tôi là tác giả và người duy trì bĩu môi.


3

Tôi đã lấy câu trả lời của sth và sửa đổi nó một chút để phù hợp với nhu cầu của tôi về một từ điển và danh sách lồng nhau:

def pretty(d, indent=0):
    if isinstance(d, dict):
        for key, value in d.iteritems():
            print '\t' * indent + str(key)
            if isinstance(value, dict) or isinstance(value, list):
                pretty(value, indent+1)
            else:
                print '\t' * (indent+1) + str(value)
    elif isinstance(d, list):
        for item in d:
            if isinstance(item, dict) or isinstance(item, list):
                pretty(item, indent+1)
            else:
                print '\t' * (indent+1) + str(item)
    else:
        pass

Mà sau đó cho tôi đầu ra như:

>>> 
xs:schema
    @xmlns:xs
        http://www.w3.org/2001/XMLSchema
    xs:redefine
        @schemaLocation
            base.xsd
        xs:complexType
            @name
                Extension
            xs:complexContent
                xs:restriction
                    @base
                        Extension
                    xs:sequence
                        xs:element
                            @name
                                Policy
                            @minOccurs
                                1
                            xs:complexType
                                xs:sequence
                                    xs:element
                                            ...

1

Sth, tôi chìm đó là đẹp;)

def pretty(d, indent=0):
    for key, value in d.iteritems():
        if isinstance(value, dict):
            print '\t' * indent + (("%30s: {\n") % str(key).upper())
            pretty(value, indent+1)
            print '\t' * indent + ' ' * 32 + ('} # end of %s #\n' % str(key).upper())
        elif isinstance(value, list):
            for val in value:
                print '\t' * indent + (("%30s: [\n") % str(key).upper())
                pretty(val, indent+1)
                print '\t' * indent + ' ' * 32 + ('] # end of %s #\n' % str(key).upper())
        else:
            print '\t' * indent + (("%30s: %s") % (str(key).upper(),str(value)))

1
-1: Không xử lý listcác giá trị không phải là dicttrường hợp, tức là pretty({'key': [1, 2, 3]}, indent=4)==> AttributeError: 'int' object has no attribute 'iteritems'. Tôi cũng không thích nó khóa phím trên.
martineau

Giải pháp của bạn cho rằng không thể có một lệnh trong danh sách bên trong lệnh gốc. Ngoài ra, nó xem xét rằng chúng tôi không muốn in một danh sách hoặc một tuple. Cuối cùng, không viết hoa các khóa, kết quả cho {'a': 0, 'A': 1} sẽ không chính xác.
y.petremann

1
This class prints out a complex nested dictionary with sub dictionaries and sub lists.  
##
## Recursive class to parse and print complex nested dictionary
##

class NestedDictionary(object):
    def __init__(self,value):
        self.value=value

    def print(self,depth):
        spacer="--------------------"
        if type(self.value)==type(dict()):
            for kk, vv in self.value.items():
                if (type(vv)==type(dict())):
                    print(spacer[:depth],kk)
                    vvv=(NestedDictionary(vv))
                    depth=depth+3
                    vvv.print(depth)
                    depth=depth-3
                else:
                    if (type(vv)==type(list())):
                        for i in vv:
                            vvv=(NestedDictionary(i))
                            depth=depth+3
                            vvv.print(depth)
                            depth=depth-3
                    else:
                        print(spacer[:depth],kk,vv) 

##
## Instatiate and execute - this prints complex nested dictionaries
## with sub dictionaries and sub lists
## 'something' is a complex nested dictionary

MyNest=NestedDictionary(weather_com_result)
MyNest.print(0)

1

Tôi đã viết mã đơn giản này để in cấu trúc chung của một đối tượng json trong Python.

def getstructure(data, tab = 0):
    if type(data) is dict:
        print ' '*tab + '{' 
        for key in data:
            print ' '*tab + '  ' + key + ':'
            getstructure(data[key], tab+4)
        print ' '*tab + '}'         
    elif type(data) is list and len(data) > 0:
        print ' '*tab + '['
        getstructure(data[0], tab+4)
        print ' '*tab + '  ...'
        print ' '*tab + ']'

kết quả cho dữ liệu sau

a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':'p','unicode':u'\xa7',("tuple","key"):"valid"}
getstructure(a)

rất nhỏ gọn và trông như thế này:

{
  function:
  tuple:
  list:
    [
      ...
    ]
  dict:
    {
      a:
      2:
    }
  unicode:
  ('tuple', 'key'):
}

0

Bản thân tôi là một người mới chơi python nhưng tôi đã làm việc với các từ điển lồng nhau trong vài tuần qua và đây là những gì tôi đã nghĩ ra.

Bạn nên thử sử dụng một ngăn xếp. Đặt các khóa từ từ điển gốc vào danh sách danh sách:

stack = [ root.keys() ]     # Result: [ [root keys] ]

Đi theo thứ tự ngược lại từ cuối đến trước, tra cứu từng khóa trong từ điển để xem giá trị của nó có phải là (cũng) một từ điển không. Nếu không, in khóa rồi xóa nó. Tuy nhiên, nếu giá trị của khóa từ điển, hãy in khóa sau đó nối các khóa cho giá trị đó vào cuối ngăn xếp và bắt đầu xử lý danh sách đó theo cùng một cách, lặp lại đệ quy cho từng danh sách khóa mới.

Nếu giá trị cho khóa thứ hai trong mỗi danh sách là một từ điển, bạn sẽ có thứ gì đó như thế này sau vài vòng:

[['key 1','key 2'],['key 2.1','key 2.2'],['key 2.2.1','key 2.2.2'],[`etc.`]]

Mặt trái của phương pháp này là thụt lề chỉ bằng \tchiều dài của ngăn xếp:

indent = "\t" * len(stack)

Nhược điểm là để kiểm tra từng khóa bạn cần băm thông qua từ điển phụ có liên quan, mặc dù điều này có thể được xử lý dễ dàng với việc hiểu danh sách và một forvòng lặp đơn giản :

path = [li[-1] for li in stack]
# The last key of every list of keys in the stack

sub = root
for p in path:
    sub = sub[p]


if type(sub) == dict:
    stack.append(sub.keys()) # And so on

Xin lưu ý rằng phương pháp này sẽ yêu cầu bạn dọn sạch các danh sách trống xóa khóa cuối cùng trong bất kỳ danh sách nào theo sau là một danh sách trống (tất nhiên có thể tạo ra một danh sách trống khác, v.v.).

Có nhiều cách khác để thực hiện phương pháp này nhưng hy vọng điều này cung cấp cho bạn một ý tưởng cơ bản về cách thực hiện.

EDIT: Nếu bạn không muốn trải qua tất cả điều đó, pprintmô-đun in từ điển lồng nhau trong một định dạng đẹp.


0

Đây là một chức năng tôi đã viết dựa trên những gì bình luận của sth. Nó hoạt động tương tự như json.dumps với thụt lề, nhưng tôi đang sử dụng các tab thay vì không gian cho thụt lề. Trong Python 3.2+, bạn có thể chỉ định thụt lề là '\ t' trực tiếp, nhưng không phải trong 2.7.

def pretty_dict(d):
    def pretty(d, indent):
        for i, (key, value) in enumerate(d.iteritems()):
            if isinstance(value, dict):
                print '{0}"{1}": {{'.format( '\t' * indent, str(key))
                pretty(value, indent+1)
                if i == len(d)-1:
                    print '{0}}}'.format( '\t' * indent)
                else:
                    print '{0}}},'.format( '\t' * indent)
            else:
                if i == len(d)-1:
                    print '{0}"{1}": "{2}"'.format( '\t' * indent, str(key), value)
                else:
                    print '{0}"{1}": "{2}",'.format( '\t' * indent, str(key), value)
    print '{'
    pretty(d,indent=1)
    print '}'

Ví dụ:

>>> dict_var = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> pretty_dict(dict_var)
{
    "a": "2",
    "b": {
        "y": {
            "t2": "5",
            "t1": "4"
        },
        "x": "3"
    }
}

Tôi không thể làm cho nó hoạt động với chính tả của giải pháp lồng nhau, bởi vì nó đã cho tôi một UnicodeEncodeError, các mục và khóa đều được chuyển đổi thành chuỗi, nếu chúng ta sử dụng các số hoặc bộ dữ liệu có chứa danh sách và ký tự thì sao? Finnaly giải pháp của bạn đưa vào tài khoản rằng đối tượng của chúng tôi, chúng tôi muốn in đẹp phải là một chính tả.
y.petremann

Tôi đã không cố viết một hàm in chung cho một lệnh python. Các bình luận được xếp hạng hàng đầu đã chứng minh làm thế nào để in đẹp một bản chính tả. Đóng góp của tôi là viết một thay thế cho json.dumps bằng '\ t' để thụt lề thay vì các tab trong python 2.7.
Al Conrad

Tôi đồng ý với bạn về việc viết một thay thế cho json.dumps, đối với tôi những vấn đề tương tự như của json.dumps được áp dụng. Ngoài ra, bạn có thể sử dụng một biểu thức chính quy đơn giản để thay đổi kiểu thụt lề, làm cho mã của bạn đơn giản hơn.
y.petremann

0

Đây là một cái gì đó sẽ in bất kỳ loại từ điển lồng nhau, trong khi theo dõi các từ điển "cha mẹ" trên đường đi.

dicList = list()

def prettierPrint(dic, dicList):
count = 0
for key, value in dic.iteritems():
    count+=1
    if str(value) == 'OrderedDict()':
        value = None
    if not isinstance(value, dict):
        print str(key) + ": " + str(value)
        print str(key) + ' was found in the following path:',
        print dicList
        print '\n'
    elif isinstance(value, dict):
        dicList.append(key)
        prettierPrint(value, dicList)
    if dicList:
         if count == len(dic):
             dicList.pop()
             count = 0

prettierPrint(dicExample, dicList)

Đây là một điểm khởi đầu tốt để in theo các định dạng khác nhau, giống như định dạng được chỉ định trong OP. Tất cả những gì bạn thực sự cần làm là các thao tác xung quanh các khối In . Lưu ý rằng có vẻ như để xem giá trị là 'OrderedDict ()'. Tùy thuộc vào việc bạn có đang sử dụng thứ gì đó từ Bộ sưu tập kiểu dữ liệu Container hay không , bạn nên tạo các loại két an toàn này để khối elif không xem nó như một từ điển bổ sung do tên của nó. Đến bây giờ, một từ điển ví dụ như

example_dict = {'key1': 'value1',
            'key2': 'value2',
            'key3': {'key3a': 'value3a'},
            'key4': {'key4a': {'key4aa': 'value4aa',
                               'key4ab': 'value4ab',
                               'key4ac': 'value4ac'},
                     'key4b': 'value4b'}

sẽ in

key3a: value3a
key3a was found in the following path: ['key3']

key2: value2
key2 was found in the following path: []

key1: value1
key1 was found in the following path: []

key4ab: value4ab
key4ab was found in the following path: ['key4', 'key4a']

key4ac: value4ac
key4ac was found in the following path: ['key4', 'key4a']

key4aa: value4aa
key4aa was found in the following path: ['key4', 'key4a']

key4b: value4b
key4b was found in the following path: ['key4']

~ thay đổi mã để phù hợp với định dạng của câu hỏi ~

lastDict = list()
dicList = list()
def prettierPrint(dic, dicList):
    global lastDict
    count = 0
    for key, value in dic.iteritems():
        count+=1
        if str(value) == 'OrderedDict()':
            value = None
        if not isinstance(value, dict):
            if lastDict == dicList:
                sameParents = True
            else:
                sameParents = False

            if dicList and sameParents is not True:
                spacing = ' ' * len(str(dicList))
                print dicList
                print spacing,
                print str(value)

            if dicList and sameParents is True:
                print spacing,
                print str(value)
            lastDict = list(dicList)

        elif isinstance(value, dict):
            dicList.append(key)
            prettierPrint(value, dicList)

        if dicList:
             if count == len(dic):
                 dicList.pop()
                 count = 0

Sử dụng cùng một mã ví dụ, nó sẽ in như sau:

['key3']
         value3a
['key4', 'key4a']
                  value4ab
                  value4ac
                  value4aa
['key4']
         value4b

Đây không phải là chính xác những gì được yêu cầu trong OP. Sự khác biệt là cha mẹ ^ n vẫn được in, thay vì vắng mặt và được thay thế bằng khoảng trắng. Để có được định dạng của OP, bạn sẽ cần thực hiện một số thao tác như sau: lặp lại so sánh dicList với lastDict . Bạn có thể làm điều này bằng cách tạo một từ điển mới và sao chép nội dung của dicList vào nó, kiểm tra xem i trong từ điển được sao chép có giống như tôi trong lastDict không và - nếu nó - viết khoảng trắng cho vị trí i đó bằng cách sử dụng hàm nhân chuỗi .


0

Từ liên kết này :

def prnDict(aDict, br='\n', html=0,
            keyAlign='l',   sortKey=0,
            keyPrefix='',   keySuffix='',
            valuePrefix='', valueSuffix='',
            leftMargin=0,   indent=1 ):
    '''
return a string representive of aDict in the following format:
    {
     key1: value1,
     key2: value2,
     ...
     }

Spaces will be added to the keys to make them have same width.

sortKey: set to 1 if want keys sorted;
keyAlign: either 'l' or 'r', for left, right align, respectively.
keyPrefix, keySuffix, valuePrefix, valueSuffix: The prefix and
   suffix to wrap the keys or values. Good for formatting them
   for html document(for example, keyPrefix='<b>', keySuffix='</b>'). 
   Note: The keys will be padded with spaces to have them
         equally-wide. The pre- and suffix will be added OUTSIDE
         the entire width.
html: if set to 1, all spaces will be replaced with '&nbsp;', and
      the entire output will be wrapped with '<code>' and '</code>'.
br: determine the carriage return. If html, it is suggested to set
    br to '<br>'. If you want the html source code eazy to read,
    set br to '<br>\n'

version: 04b52
author : Runsun Pan
require: odict() # an ordered dict, if you want the keys sorted.
         Dave Benjamin 
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403
    '''

    if aDict:

        #------------------------------ sort key
        if sortKey:
            dic = aDict.copy()
            keys = dic.keys()
            keys.sort()
            aDict = odict()
            for k in keys:
                aDict[k] = dic[k]

        #------------------- wrap keys with ' ' (quotes) if str
        tmp = ['{']
        ks = [type(x)==str and "'%s'"%x or x for x in aDict.keys()]

        #------------------- wrap values with ' ' (quotes) if str
        vs = [type(x)==str and "'%s'"%x or x for x in aDict.values()] 

        maxKeyLen = max([len(str(x)) for x in ks])

        for i in range(len(ks)):

            #-------------------------- Adjust key width
            k = {1            : str(ks[i]).ljust(maxKeyLen),
                 keyAlign=='r': str(ks[i]).rjust(maxKeyLen) }[1]

            v = vs[i]        
            tmp.append(' '* indent+ '%s%s%s:%s%s%s,' %(
                        keyPrefix, k, keySuffix,
                        valuePrefix,v,valueSuffix))

        tmp[-1] = tmp[-1][:-1] # remove the ',' in the last item
        tmp.append('}')

        if leftMargin:
          tmp = [ ' '*leftMargin + x for x in tmp ]

        if html:
            return '<code>%s</code>' %br.join(tmp).replace(' ','&nbsp;')
        else:
            return br.join(tmp)     
    else:
        return '{}'

'''
Example:

>>> a={'C': 2, 'B': 1, 'E': 4, (3, 5): 0}

>>> print prnDict(a)
{
 'C'   :2,
 'B'   :1,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, sortKey=1)
{
 'B'   :1,
 'C'   :2,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, keyPrefix="<b>", keySuffix="</b>")
{
 <b>'C'   </b>:2,
 <b>'B'   </b>:1,
 <b>'E'   </b>:4,
 <b>(3, 5)</b>:0
}

>>> print prnDict(a, html=1)
<code>{
&nbsp;'C'&nbsp;&nbsp;&nbsp;:2,
&nbsp;'B'&nbsp;&nbsp;&nbsp;:1,
&nbsp;'E'&nbsp;&nbsp;&nbsp;:4,
&nbsp;(3,&nbsp;5):0
}</code>

>>> b={'car': [6, 6, 12], 'about': [15, 9, 6], 'bookKeeper': [9, 9, 15]}

>>> print prnDict(b, sortKey=1)
{
 'about'     :[15, 9, 6],
 'bookKeeper':[9, 9, 15],
 'car'       :[6, 6, 12]
}

>>> print prnDict(b, keyAlign="r")
{
        'car':[6, 6, 12],
      'about':[15, 9, 6],
 'bookKeeper':[9, 9, 15]
}
'''

0

Tôi chỉ trở về câu hỏi này sau khi uống sth câu trả lời 's và thực hiện một thay đổi nhỏ nhưng rất hữu ích. Hàm này in tất cả các khóa trong cây JSON cũng như kích thước của các nút lá trong cây đó.

def print_JSON_tree(d, indent=0):
    for key, value in d.iteritems():
        print '    ' * indent + unicode(key),
        if isinstance(value, dict):
            print; print_JSON_tree(value, indent+1)
        else:
            print ":", str(type(d[key])).split("'")[1], "-", str(len(unicode(d[key])))

Thật tuyệt khi bạn có các đối tượng JSON lớn và muốn tìm ra vị trí của thịt. Ví dụ :

>>> print_JSON_tree(JSON_object)
key1
    value1 : int - 5
    value2 : str - 16
    key2
       value1 : str - 34
       value2 : list - 5623456

Điều này sẽ cho bạn biết rằng hầu hết dữ liệu bạn quan tâm có lẽ nằm bên trong JSON_object['key1']['key2']['value2']vì độ dài của giá trị đó được định dạng dưới dạng chuỗi là rất lớn.


0

Sử dụng chức năng này:

def pretty_dict(d, n=1):
    for k in d:
        print(" "*n + k)
        try:
            pretty_dict(d[k], n=n+4)
        except TypeError:
            continue

Gọi nó như thế này:

pretty_dict(mydict)

Điều này không hoạt động nếu các giá trị là chuỗi. Nó in từng ký tự của chuỗi trên một dòng mới, nhưng các phím có vẻ hoạt động tốt.
Anthony

0

Đây là những gì tôi nghĩ ra khi làm việc trên một lớp cần viết từ điển trong tệp .txt:

@staticmethod
def _pretty_write_dict(dictionary):

    def _nested(obj, level=1):
        indentation_values = "\t" * level
        indentation_braces = "\t" * (level - 1)
        if isinstance(obj, dict):
            return "{\n%(body)s%(indent_braces)s}" % {
                "body": "".join("%(indent_values)s\'%(key)s\': %(value)s,\n" % {
                    "key": str(key),
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for key, value in obj.items()),
                "indent_braces": indentation_braces
            }
        if isinstance(obj, list):
            return "[\n%(body)s\n%(indent_braces)s]" % {
                "body": "".join("%(indent_values)s%(value)s,\n" % {
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for value in obj),
                "indent_braces": indentation_braces
            }
        else:
            return "\'%(value)s\'" % {"value": str(obj)}

    dict_text = _nested(dictionary)
    return dict_text

Bây giờ, nếu chúng ta có một từ điển như thế này:

some_dict = {'default': {'ENGINE': [1, 2, 3, {'some_key': {'some_other_key': 'some_value'}}], 'NAME': 'some_db_name', 'PORT': '', 'HOST': 'localhost', 'USER': 'some_user_name', 'PASSWORD': 'some_password', 'OPTIONS': {'init_command': 'SET foreign_key_checks = 0;'}}}

Và chúng tôi làm:

print(_pretty_write_dict(some_dict))

Chúng tôi nhận được:

{
    'default': {
        'ENGINE': [
            '1',
            '2',
            '3',
            {
                'some_key': {
                    'some_other_key': 'some_value',
                },
            },
        ],
        'NAME': 'some_db_name',
        'OPTIONS': {
            'init_command': 'SET foreign_key_checks = 0;',
        },
        'HOST': 'localhost',
        'USER': 'some_user_name',
        'PASSWORD': 'some_password',
        'PORT': '',
    },
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.