__str__和漂亮的印刷(子)字典

时间:2011-11-15 01:22:29

标签: python pprint

我有一个主要由一个非常大的嵌套字典组成的对象:

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__(或类似的)来做到这一点?

3 个答案:

答案 0 :(得分:2)

你可以提供一个自定义的displayhook,在交互式提示符下根据你的喜好打印内置词典和其他你选择的对象:

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

它不会改变print obj行为。

我们的想法是,您的用户可以选择是否要将自定义格式用于dict

答案 1 :(得分: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的{​​{1}}方法不会影响__str__以外的任何内容。

此外,在打印嵌套对象时,the_object使用对象的pprint.pformat,而不是对象的repr

因此,为了获得我们想要的行为,我们需要str来评估类似dict的内容,但使用不同的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']) 替换嵌套字典结构中的所有dicts。

但实际上(从我的幻想命名中可以看出),我真的不希望你使用Turtle。 Dicts是如此漂亮,优化的内置,我不想添加这个中间对象只是为了实现漂亮的打印。

相反,您可以说服您的用户输入

Turtle

然后他们可以使用

from pprint import pprint

得到漂亮的印刷品。

答案 2 :(得分: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中放入不是dicts的dict-derivative,它们将被PP_dict取代。此外,如果您对这些子区域有其他参考,它们将不再指向相同的对象。

另一种方法是直接在my_object中放置一个__getitem__,它返回一个代码包装器,用于在__str__中打印当前对象的字典,覆盖__getitem__以返回代理子对象,以及以其他方式将所有的控制/操纵转发给被包裹的类。