【问题标题】:How to Print "Pretty" String Output in Python如何在 Python 中打印“漂亮”的字符串输出
【发布时间】:2011-02-22 22:25:14
【问题描述】:

我有一个字典列表,其中包含来自 sql 查询的字段 classid、dept、coursenum、area 和 title。我想以人类可读的格式输出值。我在想每个顶部的列标题,然后在每列中适当的输出,即:

CLASSID     DEPT     COURSE NUMBER        AREA     TITLE
foo         bar      foo                  bar      foo
yoo         hat      yoo                  bar      hat

(显然是标准对齐/间距)

我将如何在 python 中完成此操作?

【问题讨论】:

标签: python string terminal pretty-print


【解决方案1】:

Standard Python string formatting 可能就足够了。

# assume that your data rows are tuples
template = "{0:8}|{1:10}|{2:15}|{3:7}|{4:10}" # column widths: 8, 10, 15, 7, 10
print template.format("CLASSID", "DEPT", "COURSE NUMBER", "AREA", "TITLE") # header
for rec in your_data_source: 
  print template.format(*rec)

或者

# assume that your data rows are dicts
template = "{CLASSID:8}|{DEPT:10}|{C_NUM:15}|{AREA:7}|{TITLE:10}" # same, but named
print template.format( # header
  CLASSID="CLASSID", DEPT="DEPT", C_NUM="COURSE NUMBER", 
  AREA="AREA", TITLE="TITLE"
) 
for rec in your_data_source: 
  print template.format(**rec)

使用对齐、填充和精确格式说明符以获得最佳结果。

【讨论】:

    【解决方案2】:
    class TablePrinter(object):
        "Print a list of dicts as a table"
        def __init__(self, fmt, sep=' ', ul=None):
            """        
            @param fmt: list of tuple(heading, key, width)
                            heading: str, column label
                            key: dictionary key to value to print
                            width: int, column width in chars
            @param sep: string, separation between columns
            @param ul: string, character to underline column label, or None for no underlining
            """
            super(TablePrinter,self).__init__()
            self.fmt   = str(sep).join('{lb}{0}:{1}{rb}'.format(key, width, lb='{', rb='}') for heading,key,width in fmt)
            self.head  = {key:heading for heading,key,width in fmt}
            self.ul    = {key:str(ul)*width for heading,key,width in fmt} if ul else None
            self.width = {key:width for heading,key,width in fmt}
    
        def row(self, data):
            return self.fmt.format(**{ k:str(data.get(k,''))[:w] for k,w in self.width.iteritems() })
    
        def __call__(self, dataList):
            _r = self.row
            res = [_r(data) for data in dataList]
            res.insert(0, _r(self.head))
            if self.ul:
                res.insert(1, _r(self.ul))
            return '\n'.join(res)
    

    并在使用中:

    data = [
        {'classid':'foo', 'dept':'bar', 'coursenum':'foo', 'area':'bar', 'title':'foo'},
        {'classid':'yoo', 'dept':'hat', 'coursenum':'yoo', 'area':'bar', 'title':'hat'},
        {'classid':'yoo'*9, 'dept':'hat'*9, 'coursenum':'yoo'*9, 'area':'bar'*9, 'title':'hathat'*9}
    ]
    
    fmt = [
        ('ClassID',       'classid',   11),
        ('Dept',          'dept',       8),
        ('Course Number', 'coursenum', 20),
        ('Area',          'area',       8),
        ('Title',         'title',     30)
    ]
    
    print( TablePrinter(fmt, ul='=')(data) )
    

    生产

    ClassID     Dept     Course Number        Area     Title                         
    =========== ======== ==================== ======== ==============================
    foo         bar      foo                  bar      foo                           
    yoo         hat      yoo                  bar      hat                           
    yooyooyooyo hathatha yooyooyooyooyooyooyo barbarba hathathathathathathathathathat
    

    【讨论】:

      【解决方案3】:

      如果你想保持简单,你可以简单地将字符串左对齐到一定数量的字符:

      print string1.ljust(20) + string2.ljust(20)
      

      【讨论】:

        【解决方案4】:

        此函数将列表理解推向了一个极端,但它以最佳性能完成了您正在寻找的内容:

        算法:

        1. 在每列中查找最长的字段;即'max(map(len, column_vector))'
        2. 对于每个字段(从左到右,从上到下),调用 str.ljust 将其与其所属列的左边界对齐。
        3. 使用所需数量的分隔空格连接字段(创建一行)。
        4. 用换行符加入行集合。

        row_collection:可迭代的列表(dicts/sets/lists),每个包含一行的数据。

        key_list:指定从每一行读取哪些键/索引以形成列的列表。

        def getPrintTable(row_collection, key_list, field_sep=' '*4):
          return '\n'.join([field_sep.join([str(row[col]).ljust(width)
            for (col, width) in zip(key_list, [max(map(len, column_vector))
              for column_vector in [ [v[k]
                for v in row_collection if k in v]
                  for k in key_list ]])])
                    for row in row_collection])
        

        【讨论】:

          【解决方案5】:

          对我来说最简单的方法是转换为数组数组:

          datas = [
            [ 'ClassID', 'Dept', 'Course Number', 'Area', 'Title' ],
            [ 'foo', 'bar', 'foo', 'bar', 'foo' ],
            [ 'yoo', 'hat', 'yoo', 'bar', 'hat' ],
            [ 'line', 'last', 'fun', 'Lisa', 'Simpson' ]
          ]
          
          for j, data in enumerate(datas):
            if j == 0:
              # print(list(data))
              max = 0
              for i in datas:
                max_len =  len(''.join(i))
                if max_len > max:
                  max = max_len
                  max = max + 4 * len(datas[0])
              max = 79
              print(f"max is {max}")
              print('+' + '-' * max + '+')
              v1, v2, v3, v4, v5 = datas[0]
              print(f"|{v1:^15s}|{v2:^15s}|{v3:^15s}|{v4:^15s}|{v5:^15s}|")
              print('+' +  '-' * max + '+')
              continue
            else:
              # print( '+' + '-' * max + '+')
              v1, v2, v3, v4, v5 = data
              print(f"|{v1:^15s}|{v2:^15s}|{v3:^15s}|{v4:^15s}|{v5:^15s}|")
              print('+' +  '-' * max + '+')
              # print(type(data))
          

          你明白了:

          +-------------------------------------------------------------------------------+
          |    ClassID    |     Dept      | Course Number |     Area      |     Title     |
          +-------------------------------------------------------------------------------+
          |      foo      |      bar      |      foo      |      bar      |      foo      |
          +-------------------------------------------------------------------------------+
          |      yoo      |      hat      |      yoo      |      bar      |      hat      |
          +-------------------------------------------------------------------------------+
          |     line      |     last      |      fun      |     Lisa      |    Simpson    |
          +-------------------------------------------------------------------------------+
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-07
            • 2020-11-19
            • 2020-11-10
            • 2020-11-12
            • 1970-01-01
            相关资源
            最近更新 更多