Exercise 5.3
(a) Better output for printing objects
All Python objects have two string representations. The first
representation is created by string conversion via str()
(which is called by print
). The string representation is
usually a nicely formatted version of the object meant for humans.
The second representation is a code representation of the object
created by repr()
(or simply by viewing a value in the
interactive shell). The code representation typically shows you the
code that you have to type to get the object.
The two representations of an object are often different. For example, you can see the difference by trying the following:
>>> s = 'Hello\nWorld'
>>> print str(s) # Notice nice output (no quotes)
Hello
World
>>> print repr(s) # Notice the added quotes and escape codes
'Hello\nWorld'
>>> print '%r' % s # Alternate way to get repr() string
'Hello\nWorld'
>>>
Both kinds of string conversions can be redefined in a class if it
defines the __str__()
and __repr__()
methods.
Modify the Stock
object that you defined in Exercise 5.1
so that the __repr__()
methods
produce more useful output. For example:
>>> goog = Stock('GOOG', 100, 490.1)
>>> goog
Stock('GOOG', 100, 490.1)
>>>
See what happens when you read a portfolio of stocks and view the resulting list after you have made these changes. For example:
>>> import stock
>>> portfolio = stock.read_portfolio('Data/portfolio.csv')
>>> portfolio
... see what the output is ...
>>>
(b) Defining a custom exception
It is often good practice for libraries to define their own
exceptions. This makes it easier to distinguish between Python
exceptions raised in response to common programming errors versus
exceptions intentionally raised by a library to a signal a specific
usage problem. Modify the create_formatter()
function from the last
exercise so that it raises a custom FormatError
exception when the
user provides a bad format name. For example:
>>> from tableformat import create_formatter
>>> formatter = create_formatter('xls')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tableformat.py", line 71, in create_formatter
raise FormatError('Unknown table format %s' % name)
FormatError: Unknown table format xls
>>>
(c) An example of using getattr()
In Exercise 5.2 you worked with a function print_portfolio()
that made a table for a stock portfolio. That function was hard-coded to
only work with stock data—how limiting! You can do so much more if you
use functions such as getattr()
.
To begin, try this little example:
>>> import stock
>>> s = stock.Stock('GOOG', 100, 490.1)
>>> columns = ['name', 'shares']
>>> for colname in columns:
print colname, '=', getattr(s, colname)
name = GOOG
shares = 100
>>>
Carefully observe that the output data is determined entirely by the attribute
names listed in the columns
variable.
In the file tableformat.py
, take this idea and expand it into a generalized
function print_table()
that simply prints a table showing
user-specified attributes of a list of arbitrary objects. As with the
earlier print_portfolio()
function, print_table()
should also accept
a TableFormatter
instance to control the output format. Here’s how
it should work:
>>> import stock
>>> portfolio = stock.read_portfolio('Data/portfolio.csv')
>>> from tableformat import create_formatter, print_table
>>> formatter = create_formatter('txt')
>>> print_table(portfolio, ['name','shares'], formatter)
name shares
---------- ----------
AA 100
IBM 50
CAT 150
MSFT 200
GE 95
MSFT 50
IBM 100
>>> print_table(portfolio, ['name','shares','price'], formatter)
name shares price
---------- ---------- ----------
AA 100 32.2
IBM 50 91.1
CAT 150 83.44
MSFT 200 51.23
GE 95 40.37
MSFT 50 65.1
IBM 100 70.44
>>>
(d) Bonus: Column Formatting
Modify the print_table()
function in part (c) so that it also accepts
a list of format strings for formatting the contents of each column.
For example:
>>> print_table(portfolio,
['name','shares','price'], ['%s','%d','$%0.2f'],
formatter)
name shares price
---------- ---------- ----------
AA 100 $32.20
IBM 50 $91.10
CAT 150 $83.44
MSFT 200 $51.23
GE 95 $40.37
MSFT 50 $65.10
IBM 100 $70.44
>>>