diff --git a/Notes/00_Setup.md b/Notes/00_Setup.md index eb5b94db5..4861578cc 100644 --- a/Notes/00_Setup.md +++ b/Notes/00_Setup.md @@ -86,7 +86,7 @@ exercises. Feel free to look at this if you need a hint. To get the most out of the course however, you should try to create your own solutions first. -[Contents](Contents.md) +[Contents](Contents.md) \| [Next (1 Introduction to Python)](01_Introduction/00_Overview.md) diff --git a/Notes/01_Introduction/02_Hello_world.md b/Notes/01_Introduction/02_Hello_world.md index 0a9883dbb..1cc1bcbe5 100644 --- a/Notes/01_Introduction/02_Hello_world.md +++ b/Notes/01_Introduction/02_Hello_world.md @@ -241,7 +241,7 @@ while num_bills * bill_thickness < sears_height: day = day + 1 num_bills = num_bills * 2 -print('Number of days', days) +print('Number of days', day) ``` The statements indented below the `while` will execute as long as the expression after the `while` is `true`. @@ -257,7 +257,7 @@ while num_bills * bill_thickness < sears_height: day = day + 1 num_bills = num_bills * 2 -print('Number of days', days) +print('Number of days', day) ``` Indentation groups the following statements together as the operations that repeat: diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 1627bd4e4..c8cca87ef 100644 --- a/Notes/01_Introduction/03_Numbers.md +++ b/Notes/01_Introduction/03_Numbers.md @@ -77,7 +77,7 @@ c = -1.345e-10 Floats are represented as double precision using the native CPU representation [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754). This is the same as the `double` type in the programming language C. -> 17 digits or precision +> 17 digits of precision > Exponent from -308 to 308 Be aware that floating point numbers are inexact when representing decimals. @@ -213,14 +213,15 @@ Modify the program so that extra payment information can be more generally handl Make it so that the user can set these variables: ```python -extra_payment_start_month = 60 +extra_payment_start_month = 61 extra_payment_end_month = 108 extra_payment = 1000 ``` Make the program look at these variables and calculate the total paid appropriately. -How much will Dave pay if he pays an extra $1000/month for 4 years starting in year 5 of the mortgage? +How much will Dave pay if he pays an extra $1000/month for 4 years starting after the first +five years have already been paid? ### Exercise 1.10: Making a table @@ -234,9 +235,9 @@ The output should look something like this: 4 10736.44 497581.83 5 13420.55 496970.98 ... -308 874705.88 2971.43 -309 877389.99 299.7 -310 880074.1 -2383.16 +308 874705.88 3478.83 +309 877389.99 809.21 +310 880074.1 -1871.53 Total paid 880074.1 Months 310 ``` diff --git a/Notes/01_Introduction/04_Strings.md b/Notes/01_Introduction/04_Strings.md index 162f825f3..804f52514 100644 --- a/Notes/01_Introduction/04_Strings.md +++ b/Notes/01_Introduction/04_Strings.md @@ -28,8 +28,8 @@ Normally strings may only span a single line. Triple quotes capture all text enc including all formatting. There is no difference between using single (') versus double (") -quotes. The same type of quote used to start a string must be used to -terminate it. +quotes. *However, the same type of quote used to start a string must be used to +terminate it*. ### String escape codes diff --git a/Notes/02_Working_with_data/01_Datatypes.md b/Notes/02_Working_with_data/01_Datatypes.md index 5e7cfcbdd..cf79fd872 100644 --- a/Notes/02_Working_with_data/01_Datatypes.md +++ b/Notes/02_Working_with_data/01_Datatypes.md @@ -338,7 +338,7 @@ above. Change the number of shares to 75. ```python >>> d['shares'] = 75 >>> d -{'name': 'AA', 'shares': 75, 'price': 75} +{'name': 'AA', 'shares': 75, 'price': 32.2 } >>> ``` diff --git a/Notes/02_Working_with_data/02_Containers.md b/Notes/02_Working_with_data/02_Containers.md index 20ac55208..41833d4aa 100644 --- a/Notes/02_Working_with_data/02_Containers.md +++ b/Notes/02_Working_with_data/02_Containers.md @@ -195,12 +195,14 @@ unique = set(names) Additional set operations: ```python -names.add('CAT') # Add an item -names.remove('YHOO') # Remove an item - -s1 | s2 # Set union -s1 & s2 # Set intersection -s1 - s2 # Set difference +unique.add('CAT') # Add an item +unique.remove('YHOO') # Remove an item + +s1 = { 'a', 'b', 'c'} +s2 = { 'c', 'd' } +s1 | s2 # Set union { 'a', 'b', 'c', 'd' } +s1 & s2 # Set intersection { 'c' } +s1 - s2 # Set difference { 'a', 'b' } ``` ## Exercises diff --git a/Notes/02_Working_with_data/03_Formatting.md b/Notes/02_Working_with_data/03_Formatting.md index ae88c83b3..94b6198fe 100644 --- a/Notes/02_Working_with_data/03_Formatting.md +++ b/Notes/02_Working_with_data/03_Formatting.md @@ -49,7 +49,8 @@ b Binary integer x Hexadecimal integer f Float as [-]m.dddddd e Float as [-]m.dddddde+-xx -g Float, but selective use of E notation s String +g Float, but selective use of E notation +s String c Character (from integer) ``` @@ -114,7 +115,7 @@ modeled after the C `printf()` as well. *Note: This is the only formatting available on byte strings.* ```python ->>> b'%s has %n messages' % (b'Dave', 37) +>>> b'%s has %d messages' % (b'Dave', 37) b'Dave has 37 messages' >>> ``` diff --git a/Notes/02_Working_with_data/04_Sequences.md b/Notes/02_Working_with_data/04_Sequences.md index d74f352b9..51e2df4bf 100644 --- a/Notes/02_Working_with_data/04_Sequences.md +++ b/Notes/02_Working_with_data/04_Sequences.md @@ -242,7 +242,7 @@ for x, y in points: ``` When using multiple variables, each tuple is *unpacked* into a set of iteration variables. -The number of variables must match the of items in each tuple. +The number of variables must match the number of items in each tuple. ### zip() function diff --git a/Notes/02_Working_with_data/06_List_comprehension.md b/Notes/02_Working_with_data/06_List_comprehension.md index 11e5ae9e3..66a037a2f 100644 --- a/Notes/02_Working_with_data/06_List_comprehension.md +++ b/Notes/02_Working_with_data/06_List_comprehension.md @@ -215,7 +215,7 @@ For example, this determines the set of unique stock names that appear in `portf ```python >>> names = { s['name'] for s in portfolio } >>> names -{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT'] } +{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT' } >>> ``` diff --git a/Notes/02_Working_with_data/07_Objects.md b/Notes/02_Working_with_data/07_Objects.md index 025ecf48f..8710e3038 100644 --- a/Notes/02_Working_with_data/07_Objects.md +++ b/Notes/02_Working_with_data/07_Objects.md @@ -11,7 +11,7 @@ Many operations in Python are related to *assigning* or *storing* values. ```python a = value # Assignment to a variable -s[n] = value # Assignment to an list +s[n] = value # Assignment to a list s.append(value) # Appending to a list d['key'] = value # Adding to a dictionary ``` diff --git a/Notes/03_Program_organization/01_Script.md b/Notes/03_Program_organization/01_Script.md index 11fdb1809..cd5626c5c 100644 --- a/Notes/03_Program_organization/01_Script.md +++ b/Notes/03_Program_organization/01_Script.md @@ -283,7 +283,7 @@ interactively after running your program: >>> files = ['Data/portfolio.csv', 'Data/portfolio2.csv'] >>> for name in files: print(f'{name:-^43s}') - portfolio_report(name, 'prices.csv') + portfolio_report(name, 'Data/prices.csv') print() ... look at the output ... diff --git a/Notes/03_Program_organization/02_More_functions.md b/Notes/03_Program_organization/02_More_functions.md index 318ddc802..e169c1f98 100644 --- a/Notes/03_Program_organization/02_More_functions.md +++ b/Notes/03_Program_organization/02_More_functions.md @@ -267,7 +267,7 @@ If you were doing a lot of file parsing for real, you’d probably want to clean some of this up and make it more general purpose. That's our goal. -Start this exercise by creating a new file called +Start this exercise by opening the file called `Work/fileparse.py`. This is where we will be doing our work. ### Exercise 3.3: Reading CSV Files @@ -332,7 +332,7 @@ follows: [{'price': '32.20', 'name': 'AA', 'shares': '100'}, {'price': '91.10', 'name': 'IBM', 'shares': '50'}, {'price': '83.44', 'name': 'CAT', 'shares': '150'}, {'price': '51.23', 'name': 'MSFT', 'shares': '200'}, {'price': '40.37', 'name': 'GE', 'shares': '95'}, {'price': '65.10', 'name': 'MSFT', 'shares': '50'}, {'price': '70.44', 'name': 'IBM', 'shares': '100'}] >>> # Read only some of the data ->>> shares_held = parse_csv('portfolio.csv', select=['name','shares']) +>>> shares_held = parse_csv('Data/portfolio.csv', select=['name','shares']) >>> shares_held [{'name': 'AA', 'shares': '100'}, {'name': 'IBM', 'shares': '50'}, {'name': 'CAT', 'shares': '150'}, {'name': 'MSFT', 'shares': '200'}, {'name': 'GE', 'shares': '95'}, {'name': 'MSFT', 'shares': '50'}, {'name': 'IBM', 'shares': '100'}] >>> diff --git a/Notes/03_Program_organization/03_Error_checking.md b/Notes/03_Program_organization/03_Error_checking.md index f403507c0..2c9938c5c 100644 --- a/Notes/03_Program_organization/03_Error_checking.md +++ b/Notes/03_Program_organization/03_Error_checking.md @@ -126,7 +126,7 @@ bar() There are about two-dozen built-in exceptions. Usually the name of the exception is indicative of what's wrong (e.g., a `ValueError` is raised because you supplied a bad value). This is not an -exhaustive list. Check the documentation for more. +exhaustive list. Check the [documentation](https://docs.python.org/3/library/exceptions.html) for more. ```python ArithmeticError @@ -341,7 +341,7 @@ As a general rule, it’s usually best to skip such tests and to just let the program fail on bad inputs. The traceback message will point at the source of the problem and can assist in debugging. -The main reason for adding the above check to avoid running the code +The main reason for adding the above check is to avoid running the code in a non-sensical mode (e.g., using a feature that requires column headers, but simultaneously specifying that there are no headers). diff --git a/Notes/03_Program_organization/04_Modules.md b/Notes/03_Program_organization/04_Modules.md index 260f715ca..60a0866ec 100644 --- a/Notes/03_Program_organization/04_Modules.md +++ b/Notes/03_Program_organization/04_Modules.md @@ -212,8 +212,8 @@ not readily accessible from the current working directory. ## Exercises For this exercise involving modules, it is critically important to -make sure you are running Python in a proper environment. Modules are -usually when programmers encounter problems with the current working +make sure you are running Python in a proper environment. Modules +often present new programmers with problems related to the current working directory or with Python's path settings. For this course, it is assumed that you're writing all of your code in the `Work/` directory. For best results, you should make sure you're also in that directory @@ -299,13 +299,13 @@ In section 2, you wrote a program `report.py` that produced a stock report like ``` Name Shares Price Change ---------- ---------- ---------- ---------- - AA 100 39.91 7.71 - IBM 50 106.11 15.01 - CAT 150 78.58 -4.86 - MSFT 200 30.47 -20.76 - GE 95 37.38 -2.99 - MSFT 50 30.47 -34.63 - IBM 100 106.11 35.67 + AA 100 9.22 -22.98 + IBM 50 106.28 15.18 + CAT 150 35.46 -47.98 + MSFT 200 20.89 -30.34 + GE 95 13.48 -26.89 + MSFT 50 20.89 -44.21 + IBM 100 106.28 35.84 ``` Take that program and modify it so that all of the input file diff --git a/Notes/03_Program_organization/05_Main_module.md b/Notes/03_Program_organization/05_Main_module.md index 93df5e747..0bcce5dae 100644 --- a/Notes/03_Program_organization/05_Main_module.md +++ b/Notes/03_Program_organization/05_Main_module.md @@ -263,13 +263,13 @@ should be able to run it interatively like this: >>> report.main(['report.py', 'Data/portfolio.csv', 'Data/prices.csv']) Name Shares Price Change ---------- ---------- ---------- ---------- - AA 100 39.91 7.71 - IBM 50 106.11 15.01 - CAT 150 78.58 -4.86 - MSFT 200 30.47 -20.76 - GE 95 37.38 -2.99 - MSFT 50 30.47 -34.63 - IBM 100 106.11 35.67 + AA 100 9.22 -22.98 + IBM 50 106.28 15.18 + CAT 150 35.46 -47.98 + MSFT 200 20.89 -30.34 + GE 95 13.48 -26.89 + MSFT 50 20.89 -44.21 + IBM 100 106.28 35.84 >>> ``` @@ -291,16 +291,16 @@ execute as a script on the command line: bash $ python3 report.py Data/portfolio.csv Data/prices.csv Name Shares Price Change ---------- ---------- ---------- ---------- - AA 100 39.91 7.71 - IBM 50 106.11 15.01 - CAT 150 78.58 -4.86 - MSFT 200 30.47 -20.76 - GE 95 37.38 -2.99 - MSFT 50 30.47 -34.63 - IBM 100 106.11 35.67 + AA 100 9.22 -22.98 + IBM 50 106.28 15.18 + CAT 150 35.46 -47.98 + MSFT 200 20.89 -30.34 + GE 95 13.48 -26.89 + MSFT 50 20.89 -44.21 + IBM 100 106.28 35.84 bash $ python3 pcost.py Data/portfolio.csv Total cost: 44671.15 ``` -[Contents](../Contents.md) \| [Previous (3.4 Modules)](04_Modules.md) \| [Next (3.6 Design Discussion)](06_Design_discussion.md) \ No newline at end of file +[Contents](../Contents.md) \| [Previous (3.4 Modules)](04_Modules.md) \| [Next (3.6 Design Discussion)](06_Design_discussion.md) diff --git a/Notes/04_Classes_objects/02_Inheritance.md b/Notes/04_Classes_objects/02_Inheritance.md index 360635cca..5f2db7a9f 100644 --- a/Notes/04_Classes_objects/02_Inheritance.md +++ b/Notes/04_Classes_objects/02_Inheritance.md @@ -277,7 +277,7 @@ inheritance instead. To start, focus on the steps that are involved in a creating a table. At the top of the table is a set of table headers. After that, rows -of table data appear. Let's take those steps and and put them into +of table data appear. Let's take those steps and put them into their own class. Create a file called `tableformat.py` and define the following class: diff --git a/Notes/04_Classes_objects/03_Special_methods.md b/Notes/04_Classes_objects/03_Special_methods.md index 460009ef2..72a8ef936 100644 --- a/Notes/04_Classes_objects/03_Special_methods.md +++ b/Notes/04_Classes_objects/03_Special_methods.md @@ -147,7 +147,8 @@ A method that has not yet been invoked by the function call operator `()` is kno It operates on the instance where it originated. ```python ->>> s = Stock('GOOG', 100, 490.10) >>> s +>>> s = Stock('GOOG', 100, 490.10) +>>> s >>> c = s.cost >>> c diff --git a/Notes/05_Object_model/02_Classes_encapsulation.md b/Notes/05_Object_model/02_Classes_encapsulation.md index 49feb3c81..f3147fc74 100644 --- a/Notes/05_Object_model/02_Classes_encapsulation.md +++ b/Notes/05_Object_model/02_Classes_encapsulation.md @@ -95,8 +95,8 @@ One approach: introduce accessor methods. class Stock: def __init__(self, name, shares, price): self.name = name - self.set_shares(shares) - self.price = price + self.set_shares(shares) + self.price = price # Function that layers the "get" operation def get_shares(self): diff --git a/Notes/06_Generators/01_Iteration_protocol.md b/Notes/06_Generators/01_Iteration_protocol.md index c22fab6a2..787b02143 100644 --- a/Notes/06_Generators/01_Iteration_protocol.md +++ b/Notes/06_Generators/01_Iteration_protocol.md @@ -42,9 +42,9 @@ _iter = obj.__iter__() # Get iterator object while True: try: x = _iter.__next__() # Get next item + # statements ... except StopIteration: # No more items break - # statements ... ``` All the objects that work with the `for-loop` implement this low-level diff --git a/Notes/06_Generators/03_Producers_consumers.md b/Notes/06_Generators/03_Producers_consumers.md index ffd7845b5..5c1b8cb5f 100644 --- a/Notes/06_Generators/03_Producers_consumers.md +++ b/Notes/06_Generators/03_Producers_consumers.md @@ -20,7 +20,7 @@ def follow(f): ... # Consumer -for line in follow(f): # Consumes vale from `yield` above +for line in follow(f): # Consumes value from `yield` above ... ``` @@ -124,6 +124,7 @@ opening a file--it merely operates on a sequence of lines given to it as an argument. Now, try this: ``` +>>> from follow import follow >>> lines = follow('Data/stocklog.csv') >>> ibm = filematch(lines, 'IBM') >>> for line in ibm: diff --git a/Notes/07_Advanced_Topics/03_Returning_functions.md b/Notes/07_Advanced_Topics/03_Returning_functions.md index 30e6f0772..c5f1eb935 100644 --- a/Notes/07_Advanced_Topics/03_Returning_functions.md +++ b/Notes/07_Advanced_Topics/03_Returning_functions.md @@ -29,7 +29,7 @@ Adding 3 4 ### Local Variables -Observe how to inner function refers to variables defined by the outer +Observe how the inner function refers to variables defined by the outer function. ```python @@ -86,6 +86,7 @@ Consider a function like this: ```python def after(seconds, func): + import time time.sleep(seconds) func() ``` @@ -110,6 +111,7 @@ def add(x, y): return do_add def after(seconds, func): + import time time.sleep(seconds) func() diff --git a/Notes/08_Testing_debugging/03_Debugging.md b/Notes/08_Testing_debugging/03_Debugging.md index 378a6a36f..f8f7de0a6 100644 --- a/Notes/08_Testing_debugging/03_Debugging.md +++ b/Notes/08_Testing_debugging/03_Debugging.md @@ -4,7 +4,7 @@ ### Debugging Tips -So, you're program has crashed... +So, your program has crashed... ```bash bash % python3 blah.py diff --git a/Notes/09_Packages/02_Third_party.md b/Notes/09_Packages/02_Third_party.md index 2fa5e5508..2f1086cdd 100644 --- a/Notes/09_Packages/02_Third_party.md +++ b/Notes/09_Packages/02_Third_party.md @@ -50,6 +50,7 @@ the same steps as above: ```python >>> import numpy +>>> numpy >>> ``` @@ -120,7 +121,7 @@ different problem. ### Handling Third-Party Dependencies in Your Application If you have written an application and it has specific third-party -dependencies, one challange concerns the creation and preservation of +dependencies, one challenge concerns the creation and preservation of the environment that includes your code and the dependencies. Sadly, this has been an area of great confusion and frequent change over Python's lifetime. It continues to evolve even now. diff --git a/Solutions/1_10/mortgage.py b/Solutions/1_10/mortgage.py index dabd94fc3..51e477519 100644 --- a/Solutions/1_10/mortgage.py +++ b/Solutions/1_10/mortgage.py @@ -7,7 +7,7 @@ month = 0 extra_payment = 1000.0 -extra_payment_start_month = 60 +extra_payment_start_month = 61 extra_payment_end_month = 108 while principal > 0: @@ -15,7 +15,7 @@ principal = principal * (1+rate/12) - payment total_paid = total_paid + payment - if month > extra_payment_start_month and month <= extra_payment_end_month: + if month >= extra_payment_start_month and month <= extra_payment_end_month: principal = principal - extra_payment total_paid = total_paid + extra_payment diff --git a/Work/bounce.py b/Work/bounce.py index 3660ddd82..fc638ce34 100644 --- a/Work/bounce.py +++ b/Work/bounce.py @@ -1,3 +1,10 @@ # bounce.py # # Exercise 1.5 +height = 100 +counter = 0 + +while counter < 10: + counter += 1 + height -= height*(2/5) + print(counter, round(height, 4)) diff --git a/Work/mortgage.py b/Work/mortgage.py index d527314e3..25cc35fd2 100644 --- a/Work/mortgage.py +++ b/Work/mortgage.py @@ -1,3 +1,26 @@ # mortgage.py # # Exercise 1.7 +principal = 500000.0 +rate = 0.05 +payment = 2684.11 +total_paid = 0.0 +month = 0 +extra_payment_start_month = 61 +extra_payment_end_month = 108 +extra_payment = 1000 + + + +while principal > 0: + month += 1 + extra_payment = 0 + if month >= extra_payment_start_month and month <= extra_payment_end_month: + extra_payment += 1000 + print(month) + principal = principal * (1+rate/12) - payment - extra_payment + total_paid = total_paid + payment + print(f'{month} {total_paid:0.2f} {principal:0.2f}') + + +print(f'Total paid: {total_paid} in {month} months') diff --git a/Work/pcost.py b/Work/pcost.py index e68aa20b4..edcf077e8 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -1,3 +1,25 @@ -# pcost.py -# -# Exercise 1.27 +import csv +import sys + +def portfolio_cost(filename): + """Read csv file with stock portfolio and compute the total cost""" + total_cost = 0 + with open(filename) as csvfile: + reader = csv.DictReader(csvfile) + for rowno, row in enumerate(reader): + try: + total_cost += int(row['shares']) * float(row['price']) + except ValueError as err: + print(f'Row {rowno}: Bad row: {row}' + f'\nThe line is not used in the computation of Total cost' + f'\nErrormessage: {err}') + return total_cost + +if __name__ == '__main__': + if len(sys.argv) == 2: + filename = sys.argv[1] + else: + filename = 'Data/portfolio.csv' + print(filename) + cost = portfolio_cost(filename) + print(f'Total cost {cost:0.2f}') diff --git a/Work/report.py b/Work/report.py index 47d5da7b1..c8405c074 100644 --- a/Work/report.py +++ b/Work/report.py @@ -1,3 +1,139 @@ # report.py # # Exercise 2.4 +import csv +from pprint import pprint +import sys + +def type_conversion(type_list, row): + """Convert values of a row into defined types + + :input: type_list - list of python functions to coerce + types, e.g. [str, int, float] + row - list of values all strings as they are + loaded from csv, e.g. ['A', '1', '1'] + return: update row with converted values + + >>> type_list = [str, int, float] + >>> row = ['a', '1', '1'] + >>> type_conversion(type_list, row) + ['a', 1, 1.0] + """ + type_row = list(zip(type_list, row)) + converted = [func(val) for func, val in type_row] + return converted + +def read_portfolio(filename, type_list=[]): + """Read csv file with stock portfolio and return the list of stocks""" + portfolio = [] + with open(filename) as csvfile: + reader = csv.reader(csvfile) + headers = next(reader) + # Fill select with field names if you only want a subset of the data + # For now we take all + select = headers + indices = [ headers.index(colname) for colname in select ] + for row in reader: + try: + row = type_conversion(type_list, row) + # dict-comprehension + # record = { colname: row[index] for colname, index in zip(select, indices) } + # Do it all in on dict comprehension just to show of. The line above is better, I'd say + record = { name: func(row[index]) for name, func, index in zip(select, type_list, indices) } + portfolio.append(record) + except ValueError as err: + print(f'Invalid line at name {row["name"]}' + f'\nThe line is discarded' + f'\nErrormessage: {err}') + return portfolio + +def read_prices(filename): + with open(filename) as csvfile: + price_dict = {} + reader = csv.reader(csvfile) + try: + for i, row in enumerate(reader, 1): + price_dict[row[0]] = float(row[1]) + except IndexError as err: + print( + f'\n\nread_prices():' + f'\nRow {i} does not have the right format' + f'\nError message: {err}\n' + ) + return price_dict + +def compute_value(portfolio, prices): + """Compute portfolio value + + :input: portfolio: list of dicts containing stocks + in format (name, amount_shares, price) + prices: dictionary of price changes + + :return: total - total value as int + """ + + # This is an example of map-reduce. The list comprehension is mapping + # an operation across the list. The sum() function is performing a + # reduction across the result. + return sum([s['shares'] * prices[s['name']] for s in portfolio]) + +def make_report(portfolio, prices): + """Use price data to compute value of portfolio stocks + + :input: portfolio: data as dict (name, shares, price) + price: dict with price changes of stocks + + :return: list of tuples containing the rows name, + share, price, change + """ + report = [] + for row in portfolio: + stock_name = row['name'] + curr_price = prices[stock_name] + change = round((curr_price - row['price']),2) + report.append((stock_name, row['shares'], curr_price, change)) + + return report + +def print_report(report, header): + """Print out the portfolio report nicely formatted""" + h = ''.join([f'{i:>10} ' for i in header]) + l = ''.join(['{:_<10} '.format('') for i in range(4)]) + output = f'{h}\n{l}\n' + for name, shares, price, change in report: + price_in_dollar = f'${price:.2f}' + output += (f'{name:>10s} {shares:>10d} {price_in_dollar:>10} {change:>10.2f}\n') + + print(output) + + + +if __name__ == '__main__': + if len(sys.argv) == 2: + param = sys.argv[1] + else: + type_list = [str, int, float] + param = 'Data/portfolio.csv' + if param == 'missing': + filename = 'Data/missing.csv' + elif param == 'dowstocks': + type_list = [str, float, str, str, float, float, float, float, int] + filename = 'Data/dowstocks.csv' + else: + filename = param + portfolio = read_portfolio(filename, type_list) + pprint(portfolio) + + # The following code assumes a shares column, + # which might not exist + if filename == 'Data/portfolio.csv': + price_file = 'Data/prices.csv' + prices = read_prices(price_file) + + portfolio_value = compute_value(portfolio, prices) + print(f'Current value of the portfolio: ${portfolio_value}') + + report = make_report(portfolio, prices) + + headers = ('Name', 'Shares', 'Price', 'Change') + print_report(report, headers) diff --git a/Work/sears.py b/Work/sears.py new file mode 100644 index 000000000..c2d2c27f6 --- /dev/null +++ b/Work/sears.py @@ -0,0 +1,14 @@ +# sears.py +bill_thickness = 0.11 * 0.001 # Meters (0.11 mm) +sears_height = 442 # Height (meters) +num_bills = 1 +day = 1 + +while num_bills * bill_thickness < sears_height: + print(day, num_bills, num_bills * bill_thickness) + day = day + 1 + num_bills = num_bills * 2 + +print('Number of days', day) +print('Number of bills', num_bills) +print('Final height', num_bills * bill_thickness)