2014-01-29 48 views
0

我使用pprint很好地打印dict,它的工作正常。現在我切換到使用模塊collections中的OrderedDict。不幸的是,pprint路由似乎並沒有認識到這些對象或多或少都是dict,並且退回到打印這條長線。漂亮打印OrderedDicts使用pprint

>>> d = { i:'*'*i for i in range(8) } 
>>> pprint.pprint(d) 
{0: '', 
1: '*', 
2: '**', 
3: '***', 
4: '****', 
5: '*****', 
6: '******', 
7: '*******'} 
>>> pprint.pprint(collections.OrderedDict(d)) 
OrderedDict([(0, ''), (1, '*'), (2, '**'), (3, '***'), (4, '****'), (5, '*****'), (6, '******'), (7, '*******')]) 

還有什麼方法可以更好地表示OrderedDict s?也許即使它們嵌套在裏面正常dictlist

回答

2

試試這個上:

d = collections.OrderedDict({ i:'*'*i for i in range(8) })

編輯

pprint.pprint(list(d.items()))

+0

是的,好吧,好的。這看起來像一個元組列表,不再像'dict'一樣。我希望看起來像一個字典(也許只是忽略了這是一個有序的事實)的表示。 – Alfe

+1

我認爲你甚至可以在'd.items()'的周圍去掉'list'。但我仍然想知道爲什麼'pprint'甚至在OrderedDict中存在這樣的問題;畢竟他們正在諷刺「字典」。 – Alfe

+0

啊,我認爲它是否在一個基於「也許即使它們嵌套在一個正常字典或列表裏面」的列表中也沒關係? – misakm

3

我發現這是一個相對簡單的解決方案,但它包含使輸出爲您訂購的風險字典看起來就好像它是一個普通的dict對象。

使用上下文管理器防止pprint對字典鍵進行排序的原始解決方案來自this answer

@contextlib.contextmanager 
def pprint_OrderedDict(): 
    pp_orig = pprint._sorted 
    od_orig = OrderedDict.__repr__ 
    try: 
     pprint._sorted = lambda x:x 
     OrderedDict.__repr__ = dict.__repr__ 
     yield 
    finally: 
     pprint._sorted = pp_orig 
     OrderedDict.__repr__ = od_orig 

(你也可以只修補OrderedDict.__repr__dict.__repr__,但請不要。)

例子:

>>> foo = [('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'), 
...  ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')] 

>>> d = OrderedDict(foo) 
>>> pprint.pprint(d) 
OrderedDict([('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'), ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')]) 

>>> pprint.pprint(dict(d)) 
{'Bill': 'Associate', 
'Bob': 'Manager', 
'Diane': 'Manager', 
'Ian': 'Associate', 
'Melinda': 'Associate', 
'Roger': 'Owner'} 

>>> with pprint_OrderedDict(): 
...  pprint.pprint(d) 
... 
{'Roger': 'Owner', 
'Diane': 'Manager', 
'Bob': 'Manager', 
'Ian': 'Associate', 
'Bill': 'Associate', 
'Melinda': 'Associate'} 
1

如果你是專門針對CPython的* 3.6或更高版本,那麼你可以just use regular dictionaries而不是OrderedDict。你會錯過幾個methods exclusive to OrderedDict,並且它(但)不能保證可以移植到其他Python實現中,但它可能是完成你所要做的最簡單的方法。

* CPython是Python的參考實現,可以從python.org下載。
** CPython stole this idea from PyPy,所以你也可以依靠它在那裏工作。

+0

有趣!但是目前他們表示,直到未來可能發生的語言規範發生變化之前,不應該依賴它。好吧,嗯。 – Alfe

0

我意識到這是一種necroposting,但我想我會張貼我使用的東西。它的主要優點是可以將它的輸出讀回到python中,從而允許在表示之間關閉(例如,我使用JSON文件)。當然,它通過從其內部的_format函數中剝離一些代碼來打破pprint封裝。

#!/bin/env python 
from __future__ import print_function 

import pprint; 
from collections import OrderedDict 
import json 
import sys 


class MyPP (pprint.PrettyPrinter): 
    def _format(self, object, stream, indent, allowance, context, level): 
     if not isinstance(object, OrderedDict) : 
      return pprint.PrettyPrinter._format(self, object, stream, indent, allowance, context, level) 
     level = level + 1 
     objid = id(object) 
     if objid in context: 
      stream.write(_recursion(object)) 
      self._recursive = True 
      self._readable = False 
      return 
     write = stream.write 
     _len=len 
     rep = self._repr(object, context, level - 1) 
     typ = type(object) 
     sepLines = _len(rep) > (self._width - 1 - indent - allowance) 

     if self._depth and level > self._depth: 
      write(rep) 
      return 

     write('OrderedDict([\n%s'%(' '*(indent+1),)) 
     if self._indent_per_level > 1: 
      write((self._indent_per_level - 1) * ' ') 
     length = _len(object) 
     #import pdb; pdb.set_trace() 
     if length: 
      context[objid] = 1 
      indent = indent + self._indent_per_level 
      items = object.items() 
      key, ent = items[0] 
      rep = self._repr(key, context, level) 
      write('(') 
      write(rep) 
      write(', ') 
      self._format(ent, stream, indent + _len(rep) + 2, 
         allowance + 1, context, level) 
      write(')') 
      if length > 1: 
       for key, ent in items[1:]: 
        rep = self._repr(key, context, level) 
        if sepLines: 
         write(',\n%s(%s , ' % (' '*indent, rep)) 
        else: 
         write(', (%s , ' % rep) 
        self._format(ent, stream, indent + _len(rep) + 2, 
           allowance + 1, context, level) 
        write(')') 

      indent = indent - self._indent_per_level 
      del context[objid] 
     write('])') 
     return 

pp = MyPP(indent=1) 
handle=open(sys.argv[1],"r") 
values=json.loads(handle.read(),object_pairs_hook=OrderedDict) 
pp.pprint(values)