Added solution code
This commit is contained in:
48
Solutions/3_16/fileparse.py
Normal file
48
Solutions/3_16/fileparse.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# fileparse.py
|
||||
import csv
|
||||
|
||||
def parse_csv(filename, select=None, types=None, has_headers=True, delimiter=',', silence_errors=False):
|
||||
'''
|
||||
Parse a CSV file into a list of records with type conversion.
|
||||
'''
|
||||
if select and not has_headers:
|
||||
raise RuntimeError('select requires column headers')
|
||||
|
||||
with open(filename) as f:
|
||||
rows = csv.reader(f, delimiter=delimiter)
|
||||
|
||||
# Read the file headers (if any)
|
||||
headers = next(rows) if has_headers else []
|
||||
|
||||
# If specific columns have been selected, make indices for filtering and set output columns
|
||||
if select:
|
||||
indices = [ headers.index(colname) for colname in select ]
|
||||
headers = select
|
||||
|
||||
records = []
|
||||
for rowno, row in enumerate(rows, 1):
|
||||
if not row: # Skip rows with no data
|
||||
continue
|
||||
|
||||
# If specific column indices are selected, pick them out
|
||||
if select:
|
||||
row = [ row[index] for index in indices]
|
||||
|
||||
# Apply type conversion to the row
|
||||
if types:
|
||||
try:
|
||||
row = [func(val) for func, val in zip(types, row)]
|
||||
except ValueError as e:
|
||||
if not silence_errors:
|
||||
print(f"Row {rowno}: Couldn't convert {row}")
|
||||
print(f"Row {rowno}: Reason {e}")
|
||||
continue
|
||||
|
||||
# Make a dictionary or a tuple
|
||||
if headers:
|
||||
record = dict(zip(headers, row))
|
||||
else:
|
||||
record = tuple(row)
|
||||
records.append(record)
|
||||
|
||||
return records
|
||||
20
Solutions/3_16/pcost.py
Normal file
20
Solutions/3_16/pcost.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# pcost.py
|
||||
|
||||
import report
|
||||
|
||||
def portfolio_cost(filename):
|
||||
'''
|
||||
Computes the total cost (shares*price) of a portfolio file
|
||||
'''
|
||||
portfolio = report.read_portfolio(filename)
|
||||
return sum([s['shares'] * s['price'] for s in portfolio])
|
||||
|
||||
def main(args):
|
||||
if len(args) != 2:
|
||||
raise SystemExit('Usage: %s portfoliofile' % args[0])
|
||||
filename = args[1]
|
||||
print('Total cost:', portfolio_cost(filename))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
main(sys.argv)
|
||||
62
Solutions/3_16/report.py
Normal file
62
Solutions/3_16/report.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# report.py
|
||||
|
||||
import fileparse
|
||||
|
||||
def read_portfolio(filename):
|
||||
'''
|
||||
Read a stock portfolio file into a list of dictionaries with keys
|
||||
name, shares, and price.
|
||||
'''
|
||||
return fileparse.parse_csv(filename, select=['name','shares','price'], types=[str,int,float])
|
||||
|
||||
def read_prices(filename):
|
||||
'''
|
||||
Read a CSV file of price data into a dict mapping names to prices.
|
||||
'''
|
||||
return dict(fileparse.parse_csv(filename,types=[str,float], has_headers=False))
|
||||
|
||||
def make_report_data(portfolio,prices):
|
||||
'''
|
||||
Make a list of (name, shares, price, change) tuples given a portfolio list
|
||||
and prices dictionary.
|
||||
'''
|
||||
rows = []
|
||||
for stock in portfolio:
|
||||
current_price = prices[stock['name']]
|
||||
change = current_price - stock['price']
|
||||
summary = (stock['name'], stock['shares'], current_price, change)
|
||||
rows.append(summary)
|
||||
return rows
|
||||
|
||||
def print_report(reportdata):
|
||||
'''
|
||||
Print a nicely formated table from a list of (name, shares, price, change) tuples.
|
||||
'''
|
||||
headers = ('Name','Shares','Price','Change')
|
||||
print('%10s %10s %10s %10s' % headers)
|
||||
print(('-'*10 + ' ')*len(headers))
|
||||
for row in reportdata:
|
||||
print('%10s %10d %10.2f %10.2f' % row)
|
||||
|
||||
def portfolio_report(portfoliofile, pricefile):
|
||||
'''
|
||||
Make a stock report given portfolio and price data files.
|
||||
'''
|
||||
# Read data files
|
||||
portfolio = read_portfolio(portfoliofile)
|
||||
prices = read_prices(pricefile)
|
||||
|
||||
# Create the report data
|
||||
report = make_report_data(portfolio, prices)
|
||||
|
||||
# Print it out
|
||||
print_report(report)
|
||||
|
||||
def main(args):
|
||||
if len(args) != 3:
|
||||
raise SystemExit('Usage: %s portfile pricefile' % args[0])
|
||||
portfolio_report(args[1], args[2])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
main(sys.argv)
|
||||
Reference in New Issue
Block a user