压缩pformat()输出

时间:2015-04-01 18:08:16

标签: python python-3.x pprint

我有一个使用pformat()将字典转换为字符串的函数(无关:字符串稍后会在write()文件中插入.py )。

所以MY_DCT = {1: 11, 2: 22, 3: 33}会变成这样的字符串:

MY_DCT = {
    1: 11,
    2: 22,
    3: 33}

该功能有2个要求:

  1. Dict项必须在第一行后显示。
  2. 元素必须用4个空格缩进。
  3. 这是功能:

    import pprint    
    
    def f(obj_name, obj_body_as_dct):
    
        body = '{\n' + pprint.pformat(obj_body_as_dct, indent=4, width=1)[1:]
        name_and_equal_sign = obj_name + ' = '
    
        return name_and_equal_sign + body + '\n\n'
    
    
    d = {1: 11, 2: 22, 3: 33}
    
    print(f('MY_DCT', d))
    

    如果indent=0我收到此字符串:

    MY_DCT = {
    1: 11,
    2: 22,
    3: 33}
    

    如果indent=4我收到此字符串:

    MY_DCT = {
       1: 11,
        2: 22,
        3: 33}
    

    我检查了pformat()的{​​{3}},但我无法弄清楚如何在每一行上显示正确数量的空格。

    我知道我可以使用replace()+' '等来修复字符串,但我想知道这个额外的空格来自哪里,如果我可以通过正确设置参数来摆脱它(如果可能的话,那就是)。

    注意:如果有更好的方法来实现上述目标,请告诉我。

3 个答案:

答案 0 :(得分:2)

indentpformat的默认值为1,因此键在另一个下方显示为一个。

例如,pformat(d, indent=0, width=1)会产生此字符串:

{1: 11,
2: 22,
3: 33}

indent=1

{1: 11,
 2: 22,
 3: 33}

indent=2

{ 1: 11,
  2: 22,
  3: 33}

第一行总是少一个空格。


由于目标是在第一行之后显示dict元素,并且所有元素都缩进4个空格,因此在第一个元素之前添加单个空格并使用indent=4将对某些dicts起作用(如@所示)逻辑)。

然而像d = {1: {'a': 1, 'b': 2}, 2: 22, 3: 33}这样的词汇会显得相当难看,因为indent会影响深度大于1的词典的出现:

MY_DCT = {
    1: {   'a': 1,
           'b': 2},
    #    ^
    #    |
    # ugly
    2: 22,
    3: 33}

最吸引人的解决方案(对于我正在处理的数据)保留indent=1并为第一个元素添加3个空格,其余为4个空格。

def f(obj_name, given_dct):
    """
    Converts given dct (body) to a pretty formatted string.
    Resulting string used for file writing.

    Args:
        obj_name: (str) name of the dict
    Returns:
        (str)
    """

    string = pp.pformat(given_dct, width=1)[1:]

    new_str = ''
    for num, line in enumerate(string.split('\n')):
        if num == 0:
            # (pprint module always inserts one less whitespace for first line)
            # (indent=1 is default, giving everything one extra whitespace)
            new_str += ' '*4 + line + '\n'
        else:
            new_str += ' '*3 + line + '\n'

    return obj_name + ' = {\n' + new_str


s = f(obj_name='MY_DCT', given_dct=d)

导致此字符串:

MY_DCT = {
    1: {'a': 'aa',
        'b': [1,
              2,
              3]},
    2: 22,
    3: 33}

答案 1 :(得分:1)

参数不是打印的问题。添加换行符('\n')时会出现此问题。从这个例子可以看出:

import pprint    

def f(obj_name, obj_body_as_dct):

    body = '{' + pprint.pformat(obj_body_as_dct, indent=4, width=1, depth=1)[1:]
    name_and_equal_sign = obj_name + ' = ' + '\n'

    return '"""' + name_and_equal_sign + body + '"""' + '\n\n'


d = {1: 11, 2: 22, 3: 33}

print(f('MY_DCT', d))

输出:

"""MY_DCT = 
{   1: 11,
    2: 22,
    3: 33}"""

新行,以及在第一行打印中添加“{”是为什么只有输出的第一行似乎偏移了一小块空间。

更新#1

在对这些值进行一些修补之后,我能够匹配您想要的输出:

import pprint    

def f(obj_name, obj_body_as_dct):

    body = pprint.pformat(obj_body_as_dct, indent=4, width=1, depth=1)[1:]
    name_and_equal_sign = obj_name 

    return '"""' + name_and_equal_sign + ' = ' + '{' + '\n ' + body +'"""'  + '\n\n'  
                                                        # ^ I added a space in this newline

d = {1: 11, 2: 22, 3: 33}

print(f('MY_DCT', d))

以上代码输出:

"""MY_DCT = { 
    1: 11,
    2: 22,
    3: 33}"""

所以,实质上,你只需要换行符中的一个空格(在代码中显示)。

更新#2

在评论中提出您的建议:

  

试试这个:print(pp.pformat({1:11, 2:22, 3:33}, indent=0, width=1)),   缩进从0到2.你会注意到,它少了一个   第一行的空格。这是pformat()的构建方式。 - @ user 5061

我试过了:

import pprint as pp

for i in range(0,3):
    print(pp.pformat({1:11, 2:22, 3:33}, indent=i, width=1))

它给了我这个输出:

{1: 11,     #Indent = 0 Each entry (except 1) is indented by 0 spaces, because the "{" operator is in the way. 
2: 22,
3: 33}
{1: 11,     #Indent = 1 Each entry is indented by 1 spaces
 2: 22,
 3: 33}
{ 1: 11,    #Indent = 2 Each entry is indented by 2 spaces
  2: 22,
  3: 33}

正如您所看到的,问题仍然存在:“{
如果那不存在,则缩进甚至会持续。编码函数pformat()以调整该字符。

答案 2 :(得分:0)

Logic's answer让您了解为什么您有缩进问题。然而,作为( IMO )更简洁的方法,您可以使用json。此输出假设元素表示字典元素:

import json
obj_name = 'MY_DCT = '
obj_body_as_dct = {1: 11, 2: 22, 3: 33}

stringy = "\"\"\"" + obj_name + "{" \
          + str(json.dumps(obj_body_as_dct, indent=4, separators=(',', ': ')))[1:] + "\"\"\""
print(stringy)

<强>输出:

"""MY_DCT = {
    "1": 11,
    "2": 22,
    "3": 33
}"""