【问题标题】:Python - Print list of objects in a table [duplicate]Python - 打印表中的对象列表[重复]
【发布时间】:2014-01-17 09:55:48
【问题描述】:

我有一个有几个属性的类:

class Fighter():
    def __init__(self, name = "", gender = "", age = 0, weight = 0, win = 0, loss = 0, ko = 0, date = ""):

        self.__name = name
        self.__age = age
        self.__weight = weight
        self.__win = win
        self.__loss = loss
        self.__ko = ko
        self.__date = date

从我的程序的用户端,使用以下行在循环中创建一个对象并将其存储在一个列表中:

s = Fighter(name, gender, age, weight, wins, losses, ko, time) 

collection.append(s)

我可以按一些属性(例如姓名、体重等)对这个列表进行排序,而且效果很好。我在类中也有返回特定属性值的实例方法,例如:

def fighter_age(self):
    return str(self.__age)

我的问题是,如何将这些信息打印为一个有组织的表格,每个属性都有一个列,例如:

-----------------------------------------------------------------------
|Fighter Number|Name          |Age |Weight  |Wins|Losses|Date Added   |
|1             |Anderson Silva|39  |185     |33  | 6    |2014-01-17   |

【问题讨论】:

  • 关键问题是找到每列的正确宽度:您应该准备数据并执行第一个循环以找到每列的最大宽度(有限制,以避免超长字符串)和然后再次循环并打印
  • 如果打印不是那么重要,您是否考虑过以 csv 或 Excel 格式导出?
  • 编码提示:避免使用 __ 前缀,因为它们会导致“奇怪”行为(有关编码风格,请参阅 python.org/dev/peps/pep-0008

标签: python arrays list sorting object


【解决方案1】:

检查重复的链接,并考虑这样做:

import sys
def prt_width(str, width):
    sys.stdout.write('|' + str + ' '*(width-len(str)) + '|')
    sys.stdout.flush()

for fighter in collection:
    prt_width(fighter.number)
    prt_width(fighter.name)
    ...
    prt_width('\n')

注意:这需要您提前计算每个字段的最大长度(例如,您需要遍历所有名称并确定所有名称的最大长度,然后再提交它们以供打印,或者只是找到一个标准通常有效的值)。这是一种手动方法,出于某种原因,我倾向于使用手动方法来学习东西。检查重复链接以获取为您考虑的优秀库:)

【讨论】:

    【解决方案2】:

    如果您想在这方面稍微聪明一点,并使用类为您提供的一些功能,您可以将每个实例属性的最宽条目的宽度存储为类属性:

    class Fighter():
        max_name_len = 4 # start with width of header 'Name'
        ...
    
        def __init__(self, name, ...):
            if len(name) > Fighter.max_name_len :
                Fighter.max_name_len = len(name)
            ...
    

    您可以在每次创建新的Fighter 或更改其中一个属性时更新这些类属性(请参阅property,了解如何包装可能随检查代码而更改的属性)。这使您无需在每次要构建表时都循环访问collection

    然后您可以创建一个实例方法来为每个实例生成行条目:

        def table_row(self, num): # note argument for fighter number
            # return string with appropriate widths
    

    还有一个类方法来做标题:

        @classmethod
        def table_header(cls):
            # return strings with headers
    

    那么当你打印出表格时,它看起来像:

    print Fighter.table_header()
    for num, fighter in enumerate(collection, 1):
        print fighter.table_row(num)
    

    这里enumerate 为您提供collection 中每个Fighter 的编号,以1 开头,以及实际的Fighter 对象。

    【讨论】: