1

I have a class with several attributes:

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

From the user end of my program, an object is created and stored in a list using the following lines in a loop:

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

collection.append(s)

I am able to sort this list by a number of attributes, such as name, weight, etc. and that works perfectly. I also have instance methods inside the class that return the value of a specific attribute, such as:

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

My question is, how do I print this information as an organized table, with a column for each attribute, such as:

-----------------------------------------------------------------------
|Fighter Number|Name          |Age |Weight  |Wins|Losses|Date Added   |
|1             |Anderson Silva|39  |185     |33  | 6    |2014-01-17   |
Bartosz Marcinkowski
  • 6,651
  • 4
  • 39
  • 69
user2963829
  • 11
  • 1
  • 2
  • The key issue is finding the correct width of each column: you should prepare your data and do a first loop to find the largest width for each column (with a limit, to avoid extra long strings) and then loop again and print – Don Jan 17 '14 at 10:01
  • If printing is not so important, have you considered exporting in csv or Excel? – Don Jan 17 '14 at 10:01
  • 1
    coding tip: avoid __ prefixes, as they lead to 'strange' behaviours (see http://www.python.org/dev/peps/pep-0008/ for coding style) – Don Jan 17 '14 at 10:03

2 Answers2

0

Check the duplicate link, and consider doing:

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')

Note: This would require you to calculate the maximun length of each field in advance (for instance, you need to loop through all names and determain the maximum length of a all names before submitting them for print, or just find a standard value that usually works). This is a manual approach, for some reason i tend to argue for going with manual approaches to learn stuff. Check the duplicate link for good libraries that does the thinking for you :)

Torxed
  • 22,866
  • 14
  • 82
  • 131
0

If you wanted to be a bit clever about this, and use some of the functionality having a class gives you, you could store the width of the widest entry for each instance attribute as a class attribute:

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)
        ...

You can update these class attributes each time you create a new Fighter or change one of the their attributes (see property for how to wrap the attributes that might change with checking code). This saves you from needing to loop through collection each time you want to build the table.

You could then create an instance method to produce the line entry for each instance:

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

and a class method to do the headers:

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

Then when you print out the table, it looks like:

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

Here enumerate gives you the number for each Fighter in collection, starting with 1, as well as the actual Fighter objects.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437