【问题标题】:How to extend pretty print module to tables?如何将漂亮的打印模块扩展到表格?
【发布时间】:2011-03-20 04:07:42
【问题描述】:

我有漂亮的打印模块,我准备了它,因为我不高兴 pprint 模块为具有一个列表列表的数字列表生成了无数行。这是我的模块的使用示例。

    >>> a=range(10)
    >>> a.insert(5,[range(i) for i in range(10)])
    >>> a
    [0, 1, 2, 3, 4, [[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]], 5, 6, 7, 8, 9]
    >>> import pretty
    >>> pretty.ppr(a,indent=6)

    [0, 1, 2, 3, 4, 
          [
            [], 
            [0], 
            [0, 1], 
            [0, 1, 2], 
            [0, 1, 2, 3], 
            [0, 1, 2, 3, 4], 
            [0, 1, 2, 3, 4, 5], 
            [0, 1, 2, 3, 4, 5, 6], 
            [0, 1, 2, 3, 4, 5, 6, 7], 
            [0, 1, 2, 3, 4, 5, 6, 7, 8]], 5, 6, 7, 8, 9]

代码是这样的:

""" pretty.py prettyprint module version alpha 0.2
    mypr: pretty string function
    ppr:  print of the pretty string
    ONLY list and tuple prettying implemented!
"""
def mypr(w, i = 0, indent = 2, nl = '\n') :
    """ w = datastructure, i = indent level, indent = step size for indention """
    startend = {list : '[]', tuple : '()'}
    if type(w) in (list, tuple) :
        start, end = startend[type(w)]
        pr = [mypr(j, i + indent, indent, nl) for j in w]
        return nl + ' ' * i + start + ', '.join(pr) + end
    else :  return repr(w)

def ppr(w, i = 0, indent = 2, nl = '\n') :
    """ see mypr, this is only print of mypr with same parameters """
    print mypr(w, i, indent, nl)

这是我的漂亮打印模块中用于表格打印的一个固定文本:

## let's do it "manually"
width = len(str(10+10))
widthformat = '%'+str(width)+'i'
for i in range(10):
    for j in range(10):
        print widthformat % (i+j),
    print

对于漂亮的打印模块,您是否有更好的替代方案来使这段代码足够通用?

我在发布问题后发现这种常规案例是这个模块:prettytable A simple Python library for easily displaying tabular data in a visually appealing ASCII table format

【问题讨论】:

  • 您的问题有点像“为什么它完全按照我告诉它的那样做?”。答案是你对它应该为你做什么的期望与它的作用不符。
  • 我期望生成器应该为解释器产生有用的结果。图标语言很好地给出了 0..n 个答案。图标语言未能满足我对解释性使用的期望,而 Python 主要满足了这一点。期望和懒惰是发展的源泉:)
  • 发电机不能打印,因为它们不能倒带(根据定义)。所以,你的期望毫无意义,很高兴它们没有被满足:p 你所说的0 .. n 是 Python 中的xrange(0, n),它们有一个非常合理的表示。
  • xrange 在实现上仅限于 C 长数字,并且 range 相对于 xrange 的好处通常很小。如果您阅读我关于素筛优化的帖子,差异仍然存在(实际上最明智的优化是用 C 编码或使用 psyco)。

标签: python formatting generator


【解决方案1】:

如果您正在寻找合适的矩阵格式,numpy 的输出看起来非常棒:

from numpy import *
print array([[i + j for i in range(10)] for j in range(10)])

输出:

[[ 0  1  2  3  4  5  6  7  8  9]
 [ 1  2  3  4  5  6  7  8  9 10]
 [ 2  3  4  5  6  7  8  9 10 11]
 [ 3  4  5  6  7  8  9 10 11 12]
 [ 4  5  6  7  8  9 10 11 12 13]
 [ 5  6  7  8  9 10 11 12 13 14]
 [ 6  7  8  9 10 11 12 13 14 15]
 [ 7  8  9 10 11 12 13 14 15 16]
 [ 8  9 10 11 12 13 14 15 16 17]
 [ 9 10 11 12 13 14 15 16 17 18]]

【讨论】:

  • 这个解决方案很好,但不够通用,无法放入漂亮的打印模块。对我第一次要求尽可能自动执行此操作的良好响应。从您的代码布局中,我决定将其他行更改为 else :return str(w)
【解决方案2】:

你可以写:

'\n'.join(  # join the lines with '\n'
       ' '.join(  # join one line with ' '
              "%2d" % (i + j) # format each item
        for i in range(10))
    for j in range(10))

【讨论】:

  • 一点也不差,但是每天我仍然觉得做这种串联字符串的技巧很难看,每天我都认为这是一个超级Pythonic,在写作时对自己微笑这样一个聪明的 Pythonic 代码('\n'.join 而不是多次打印)。
【解决方案3】:

使用George Sakkis' table indention recipe:

print(indent(((i + j for i in range(10)) for j in range(10)),
             delim=' ', justify='right'))

产量:

0  1  2  3  4  5  6  7  8  9
1  2  3  4  5  6  7  8  9 10
2  3  4  5  6  7  8  9 10 11
3  4  5  6  7  8  9 10 11 12
4  5  6  7  8  9 10 11 12 13
5  6  7  8  9 10 11 12 13 14
6  7  8  9 10 11 12 13 14 15
7  8  9 10 11 12 13 14 15 16
8  9 10 11 12 13 14 15 16 17
9 10 11 12 13 14 15 16 17 18

附言。为了使上述工作,我对食谱做了一个小改动。我把wrapfunc(item)改成了wrapfunc(str(item))

def rowWrapper(row):
    newRows = [wrapfunc(str(item)).split('\n') for item in row]

【讨论】:

  • 看起来很简单,直到您查看链接配方背后的代码量。与我的漂亮函数的 9 条非注释行相比。
【解决方案4】:

【讨论】:

    猜你喜欢
    • 2012-05-11
    • 2013-01-20
    • 2012-10-04
    • 1970-01-01
    • 2012-05-04
    • 2012-03-31
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    相关资源
    最近更新 更多