我有一个主要由一个非常大的嵌套字典组成的对象:
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__(或类似的)来做到这一点?
答案 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
的控制之内。当您浏览level1
,level2
和level3
时,只有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__
以返回代理子对象,以及以其他方式将所有的控制/操纵转发给被包裹的类。