Come stampare piuttosto dizionari annidati?


289

Come posso stampare un dizionario con una profondità di ~ 4 in Python? Ho provato a stampare piuttosto conpprint() , ma non ha funzionato:

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

Voglio semplicemente un rientro ( "\t") per ogni annidamento, in modo da ottenere qualcosa del genere:

key1
    value1
    value2
    key2
       value1
       value2

eccetera.

Come posso fare questo?


29
Cosa significa "non ha funzionato"? Si prega di specificare con precisione come pprint "non ha funzionato".
S. Lott,

5
Ora ho usato 3 di queste risposte (ciascuna buona in uno scenario specifico): @ La risposta json di Ken è buona ma fallisce a volte quando l'oggetto non può essere serializzabile json (genera un'eccezione). se la risposta json di @ Ken non funziona, prova la risposta yaml di @ Andy e dovrebbe funzionare ma l'output della stringa è un po 'meno leggibile dall'uomo. [@ sth's answer] è la più generica (dovrebbe funzionare per qualsiasi oggetto e non usa librerie).
Trevor Boyd Smith,

Risposte:


143

Non sono sicuro di come appaia esattamente la formattazione, ma potresti iniziare con una funzione come questa:

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
Sai che la risposta convenzionale di Ken è molto meglio di così. Json gestisce già tutto e questo può dare errori come: UnicodeEncodeError: il codec 'ascii' non può codificare il carattere u '\ xf3' nella posizione 50: ordinale non nel range (128)
wonderwhy

Non riesco a farlo funzionare con il dict nidificato della mia soluzione, perché mi ha dato un UnicodeEncodeError, inoltre non stampa la chiave dict, non va all'interno dell'elenco e delle tuple e non mantiene una sintassi valida per Python.
y.petremann,

Questa risposta ha funzionato come un incantesimo per me, tuttavia ho pubblicato una nuova domanda stackoverflow.com/questions/36972225/… che stabilisce un limite al numero di valori da stampare.
gsamaras,

Piuttosto buono. Se hai elenchi nidificati come nella domanda del PO, devi aggiungere un po 'di gestione per quello. Se stai riscontrando problemi in Py2, è possibile che non riesca a gestire Unicode correttamente senza hack come __future__quello menzionato nella risposta, quindi devi impiegarli ovunque sia necessario (o aggiornare a 3 già).
sudo,

Questo ha funzionato abbastanza bene per me: 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

Il mio primo pensiero è stato che il serializzatore JSON è probabilmente abbastanza buono nei dizionari nidificati, quindi trufferei e userei quello:

>>> 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
        }
    }
}

41
Questo è interessante, ma non stampa bene tutti i dizionari. print json.dumps (myObject .__ dict__, sort_keys = True, indent = 4) #TypeError: <object at 0x0000000002E6A748> non è JSON serializzabile
tponthieux

4
Anche se questo sembra utile, il suo output non è quello che voleva l'OP.
martineau,

2
@martineau: l'output richiesto dell'OP non ha senso, i dizionari hanno bisogno di chiavi per valore.
naught101

2
@ naught101: una bella stampante può fare tutto il necessario per produrre l'output desiderato.
martineau,

22
json.dumps utilizza una funzione di conversione come argomento facoltativo, quindi con json.dumps (myObject .__ dict__, sort_keys = True, indent = 4, deault = str) puoi almeno usare un'implementazione di oggetti di repr per stampare se stesso e aggirare il TypeError "non JSON serializzabile"
RFairey,

56

Puoi provare YAML tramite PyYAML . La sua uscita può essere ottimizzata. Suggerirei di iniziare con quanto segue:

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

Il risultato è molto leggibile; può anche essere analizzato su Python, se necessario.

Modificare:

Esempio:

>>> 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
L'uso di yaml è molto interessante perché mantiene il tipo di dati nel suo formato, l'unica cosa che posso dire è che non produce una stringa Python valida, ma può quasi essere riconvertita in Python.
y.petremann,

1
yaml non gradisce la versione di Numpy dei tipi scalari ... Non mi sorprende che non supporti gli array numpy, ma mi sarei aspettato lo stesso output per a floate anumpy.float64
PhilMacKay

questo approccio ha funzionato anche per me usando un elenco di dizionari
Grant Shannon il

36

A partire da quello che è stato fatto, non vedo nessuna bella stampante che almeno imita l'output dell'interprete Python con una formattazione molto semplice, quindi ecco la mia:

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)

Per inizializzarlo:

pretty = Formatter()

Può supportare l'aggiunta di formattatori per tipi definiti, è sufficiente creare una funzione per questa come questa e associarla al tipo desiderato con 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)

Per motivi storici, tengo la precedente stampante carina che era una funzione anziché una classe, ma entrambe possono essere utilizzate allo stesso modo, la versione di classe permette semplicemente molto di più:

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)

Per usarlo :

>>> 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'
}

Rispetto ad altre versioni:

  • Questa soluzione cerca direttamente il tipo di oggetto, quindi puoi stampare quasi tutto, non solo list o dict.
  • Non ha alcuna dipendenza.
  • Tutto è inserito in una stringa, quindi puoi fare quello che vuoi con esso.
  • La classe e la funzione sono state testate e funzionano con Python 2.7 e 3.4.
  • Puoi avere tutti i tipi di oggetti all'interno, queste sono le loro rappresentazioni e non i loro contenuti che vengono inseriti nel risultato (quindi la stringa ha virgolette, la stringa Unicode è completamente rappresentata ...).
  • Con la versione di classe, è possibile aggiungere la formattazione per ogni tipo di oggetto desiderato o modificarli per quelli già definiti.
  • la chiave può essere di qualsiasi tipo valido.
  • Il carattere di rientro e Newline può essere modificato per tutto ciò che vorremmo.
  • Dict, List e Tuples sono piuttosto stampati.

2
Questa dovrebbe sicuramente essere la soluzione accettata - la mancanza di una dipendenza da JSON è enorme.
Josh,

sarebbe bello se potesse fare oggetti convertendoli in dadi e impostando la loro chiave come tipo di oggetto
Alex Cory,

In pratica puoi sostituire il metodo format_object internamente o esternamente per farlo.
y.petremann,

set_formater - ho bisogno di due t, questo è un errore di battitura, dovrebbe essere formattatore
Nikolay Prokopyev

32

in questo modo puoi stamparlo in modo carino, ad esempio il nome del tuo dizionario è yasin

import json

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

5
Ciò presuppone che il contenuto del dizionario sia json serializzabile, il che non è necessariamente vero.
SpiXel,

8

Un'altra opzione con 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)

Produzione:

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

5

Come altri hanno pubblicato, è possibile utilizzare ricorsione / dfs per stampare i dati del dizionario nidificato e chiamare ricorsivamente se si tratta di un dizionario; altrimenti stampa i dati.

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

5

il broncio può piuttosto stampare qualsiasi cosa gli passi, ad esempio (prendendo datain prestito da un'altra risposta):

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

comporterebbe un output stampato sullo schermo come:

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

oppure puoi restituire l'output della stringa formattata del tuo oggetto:

v = pout.s(data)

Il suo caso d'uso principale è per il debug, quindi non si soffoca su istanze di oggetti o altro e gestisce l'output unicode come ci si aspetterebbe, funziona in Python 2.7 e 3.

divulgazione : sono l'autore e il manutentore del broncio.


5

Uno dei modi più pitonici per questo è usare il modulo pprint già compilato .

L'argomento di cui hai bisogno per definire la profondità di stampa è come puoi aspettarti depth

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

Questo è tutto !


3

Ho preso la risposta di sth e l'ho modificata leggermente per soddisfare le mie esigenze di dizionari ed elenchi nidificati:

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

Che poi mi dà output come:

>>> 
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, affondo che è carino;)

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: non gestisce i listvalori che non sono dictistanze, ovvero pretty({'key': [1, 2, 3]}, indent=4)==> AttributeError: 'int' object has no attribute 'iteritems'. Inoltre non mi piacciono le maiuscole.
martineau,

La tua soluzione considera che non può esserci un dict all'interno di un elenco all'interno del dict di root. Inoltre considera che non vogliamo stampare piuttosto un elenco o una tupla. Infine, non scrivere in maiuscolo le chiavi, il risultato per {'a': 0, 'A': 1} non sarebbe corretto.
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

Ho scritto questo semplice codice per stampare la struttura generale di un oggetto json in 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 + ']'

il risultato per i seguenti dati

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)

è molto compatto e si presenta così:

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

0

Sono un principiante di Python me stesso, ma ho lavorato con dizionari annidati nelle ultime due settimane e questo è quello che mi è venuto in mente.

Dovresti provare a usare uno stack. Trasforma le chiavi dal dizionario radice in un elenco di un elenco:

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

Andando in ordine inverso dall'ultimo al primo, cercare ogni chiave nel dizionario per vedere se il suo valore è (anche) un dizionario. In caso contrario, stampare la chiave quindi eliminarla. Tuttavia, se il valore per la chiave è un dizionario, stampare la chiave quindi aggiungere le chiavi per quel valore alla fine dello stack e iniziare a elaborare tale elenco nello stesso modo, ripetendo in modo ricorsivo per ogni nuovo elenco di chiavi.

Se il valore per la seconda chiave in ogni elenco fosse un dizionario, avresti qualcosa del genere dopo diversi round:

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

L'aspetto positivo di questo approccio è che il rientro è solo \tvolte la lunghezza della pila:

indent = "\t" * len(stack)

Il rovescio della medaglia è che, al fine di controllare ogni chiave, è necessario eseguire l'hash nel relativo dizionario secondario, sebbene ciò possa essere gestito facilmente con una comprensione dell'elenco e un semplice forciclo:

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

Tenere presente che questo approccio richiederà la pulizia di elenchi vuoti finali e l'eliminazione dell'ultima chiave in qualsiasi elenco seguito da un elenco vuoto (che ovviamente può creare un altro elenco vuoto e così via).

Esistono altri modi per attuare questo approccio, ma spero che questo ti dia un'idea di base su come farlo.

MODIFICA: Se non vuoi passare attraverso tutto ciò, il pprintmodulo stampa dizionari annidati in un bel formato.


0

Ecco una funzione che ho scritto sulla base del commento di sth. Funziona allo stesso modo di json.dumps con rientro, ma sto usando le schede anziché lo spazio per i rientri. In Python 3.2+ puoi specificare il rientro come '\ t' direttamente, ma non in 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 '}'

Ex:

>>> 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"
    }
}

Non riesco a farlo funzionare con il dict nidificato della mia soluzione, perché mi ha dato un UnicodeEncodeError, anche gli elementi e le chiavi sono tutti convertiti in stringhe, e se usassimo numeri o tuple che contengono liste e dadi? Alla fine la tua soluzione tiene conto del fatto che il nostro oggetto che vogliamo stampare piuttosto deve essere un motto.
y.petremann,

Non stavo cercando di scrivere una funzione di stampa generica per un dict di Python. I commenti più votati dimostrano già come stampare un dict. Il mio contributo è stato quello di scrivere un'alternativa a json.dumps con '\ t' per il rientro invece delle schede in Python 2.7.
Al Conrad,

Sono d'accordo con te sulla stesura di un'alternativa a json.dumps, per me valgono gli stessi problemi di json.dumps. Inoltre, è possibile utilizzare una semplice regex per modificare il tipo di rientro, semplificando il codice.
y.petremann,

0

Ecco qualcosa che stamperà qualsiasi tipo di dizionario nidificato, tenendo traccia dei dizionari "parent" lungo la strada.

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)

Questo è un buon punto di partenza per la stampa in base a diversi formati, come quello specificato in OP. Tutto quello che devi fare è eseguire operazioni attorno ai blocchi di stampa . Si noti che sembra vedere se il valore è 'OrderedDict ()'. A seconda che si stia utilizzando qualcosa dalle raccolte di tipi di dati contenitore , è necessario creare questo tipo di cassaforte di sicurezza in modo che blocco elif non lo veda come un dizionario aggiuntivo a causa del suo nome. A partire da ora, un dizionario di esempio come

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

stamperà

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']

~ modifica del codice per adattarlo al formato della domanda ~

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

Utilizzando lo stesso codice di esempio, stamperà quanto segue:

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

Questo non è esattamente ciò che è richiesto in OP. La differenza è che un genitore ^ n è ancora stampato, invece di essere assente e sostituito con uno spazio bianco. Per arrivare al formato OP, devi fare qualcosa del tipo: confronta ripetutamente dicList con lastDict . È possibile farlo facendo un nuovo dizionario e copiando il contenuto del dicList ad esso, verificare se ho nel dizionario copiato è lo stesso che ho in lastDict, e - se si tratta - scrive spazi a che i posizione utilizzando la funzione di stringa moltiplicatore .


0

Da questo link :

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

Sto solo tornando a questa domanda dopo aver preso la risposta di sth e aver apportato una piccola ma molto utile modifica. Questa funzione stampa tutti i tasti dell'albero JSON e le dimensioni dei nodi foglia in quell'albero.

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])))

È davvero bello quando hai oggetti JSON di grandi dimensioni e vuoi capire dove si trova la carne. Esempio :

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

Ciò ti direbbe che la maggior parte dei dati a cui tieni è probabilmente all'interno JSON_object['key1']['key2']['value2']perché la lunghezza di quel valore formattato come stringa è molto grande.


0

Usa questa funzione:

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

Chiamalo così:

pretty_dict(mydict)

Questo non funziona se i valori sono stringhe. Stampa ogni carattere della stringa su una nuova riga, ma i tasti sembrano funzionare bene.
Anthony,

0

Questo è quello che mi è venuto in mente mentre lavoravo a una classe che doveva scrivere un dizionario in un file .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

Ora, se abbiamo un dizionario come questo:

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;'}}}

E facciamo:

print(_pretty_write_dict(some_dict))

Noi abbiamo:

{
    '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': '',
    },
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.