2011-11-15 60 views
1

我有主要由一個非常大的嵌套字典的對象:__str__和漂亮的印刷的(子)的字典

class my_object(object): 
    def __init__(self): 
     self.the_dict = {} # Big, nested dictionary 

我修改__ str__通過簡單地漂亮地打印頂層字典「印刷」的對象:

def __str__(self): 
     pp = pprint.PrettyPrinter() 
     return pp.pformat(self.the_dict) 

我在這裏的目標是使用戶的生活更容易一點,當他/她細讀與IPython的對象:

print(the_object) # Pretty-prints entire dict 

這個工程向用戶展示整個字典,但我想擴大這個功能字典的子部分,以及,讓用戶可以從諸如命令得到相當打印輸出:

print(the_object.the_dict['level1']['level2']['level3']) 

(會很漂亮只打印'level3'子字典)

是否有直接的方法使用__ str__(或類似的)來做到這一點?

回答

1

你可以提供打印內置詞典和其他對象,你根據自己的口味在互動提示選擇自定義displayhook:

>>> import sys 
>>> oldhook = sys.displayhook 
>>> sys.displayhook = your_module.DisplayHook(oldhook) 

它不會改變print obj行爲。

這個想法是,你的用戶可以選擇他們是否願意使用你的自定義格式dict或不。

+0

Ooooh!閃亮!不熟悉這個功能。會給這個旋轉。謝謝! –

0

你可以轉換標的字典,以「漂亮的印刷字典」 ......也許這樣的事情會做:

class my_object(object): 
    _pp = pprint.PrettyPrinter() 

    class PP_dict(dict): 
     def __setitem__(self, key, value): 
      if isinstance(value, dict): value = PP_dict(value) 
      super(my_object.PP_dict, self).__setitem__(key, value) 

     def __str__(self): 
      return my_object.pp(self) 

    @property 
    def the_dict(self): 
     return self.__dict__[ 'the_dict' ] 

    @the_dict.setter 
    def the_dict(self, value): 
     self.__dict__[ 'the_dict' ] = my_object.PP_dict(value) 

該物業只是因爲我不知道你是怎麼設置/操作「the_dict 」。

這種方法是有限的 - 例如,如果你把那些不是在the_dict中的字典的字典衍生物,它們將被PP_dict取代。此外,如果您有其他參考這些細節,他們將不再指向相同的對象。

另一種方法是把一個__getitem__在my_object直接返回了那個漂亮的打印當前對象__str__詞典中的代理包裝,覆蓋__getitem__返回代理的子對象,否則轉發所有acccess /操作的包裝類。

1

當用戶說

print(the_object.the_dict['level1']['level2']['level3']) 

Python的評估the_object.the_dict['level1']['level2']['level3']和(假設),發現它是一個字典,並傳遞到print

由於the_object.the_dict是字典,其餘的是the_object的控制。當您深入瞭解level1level2level3時,只有由the_object.the_dict['level1']['level2']['level3']返回的對象類型纔會影響print的行爲方式。 the_object__str__方法不會影響the_object本身之外的任何內容。

此外,在打印嵌套對象時,pprint.pformat使用對象的repr,而不是對象的str

因此,爲了得到我們想要的那樣行事,我們需要the_object.the_dict['level1']['level2']['level3']評估的東西像一個字典,但有不同的__repr__ ...


你可以做一個類似字典的對象(例如,Turtle),並使用Turtles一路下滑:

import collections 
import pprint 

class Turtle(collections.MutableMapping): 
    def __init__(self,*args,**kwargs): 
     self._data=dict(*args,**kwargs) 
    def __getitem__(self,key): 
     return self._data[key] 
    def __setitem__(self, key, value): 
     self._data[key]=value 
    def __delitem__(self, key): 
     del self._data[key] 
    def __iter__(self): 
     return iter(self._data) 
    def __len__(self): 
     return len(self._data) 
    def __contains__(self, x): 
     return x in self._data 
    def __repr__(self): 
     return pprint.pformat(self._data) 

class MyObject(object): 
    def __init__(self): 
     self.the_dict=Turtle() 
    def __repr__(self): 
     return repr(self.the_dict) 

the_object=MyObject() 
the_object.the_dict['level1']=Turtle() 
the_object.the_dict['level1']['level2']=Turtle() 
the_object.the_dict['level1']['level2']['level3']=Turtle({i:i for i in range(20)}) 
print(the_object) 
print(the_object.the_dict['level1']['level2']['level3']) 

要使用此功能,您必須Turtle小號取代你嵌套字典結構中的所有類型的字典。

但真的(正如你可以從我的幻想命名中看出的那樣),我並不真的希望你使用Turtle s。字典是很好的,優化的內置函數,我不想添加這個中間對象來實現漂亮的打印效果。

相反,如果你能說服你的用戶鍵入

from pprint import pprint 

那麼他們可以只使用

pprint(the_object.the_dict['level1']['level2']['level3']) 

變得相當打印。

+0

好邏輯。我得出了同樣的結論。謝謝! –