From a12eac956d434ac42761c8e7ec3229ca6041f0b3 Mon Sep 17 00:00:00 2001 From: Paul Deng Date: Sat, 20 Jun 2020 15:12:17 -0400 Subject: [PATCH 01/55] Update 04_Strings.md Personally, I think this statement should have an emphasize to mark its relative importance. --- Notes/01_Introduction/04_Strings.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 2f2f5eaeb567242a12d9ca0c4f6b38a799a181f8 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 21 Jun 2020 06:36:55 -0500 Subject: [PATCH 02/55] Fix typo --- Notes/01_Introduction/02_Hello_world.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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: From 24cd6df9cfb243bde7e90f01f4d64c385c899b6c Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 21 Jun 2020 06:42:00 -0500 Subject: [PATCH 03/55] Minor tweak to exercise 1.9 --- Notes/01_Introduction/03_Numbers.md | 4 ++-- Solutions/1_10/mortgage.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 1627bd4e4..202f07142 100644 --- a/Notes/01_Introduction/03_Numbers.md +++ b/Notes/01_Introduction/03_Numbers.md @@ -213,14 +213,14 @@ 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 in year 5 of the mortgage? ### Exercise 1.10: Making a table 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 From 5ea03f60f99f832c0291f2f936c1e30ae2afe456 Mon Sep 17 00:00:00 2001 From: Gabriel Sroka Date: Mon, 22 Jun 2020 13:49:21 -0700 Subject: [PATCH 04/55] Update 03_Debugging.md fix minor typo --- Notes/08_Testing_debugging/03_Debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 41a4a1e3c16f993007971df44f57e74d8fc7badc Mon Sep 17 00:00:00 2001 From: David Beazley Date: Tue, 30 Jun 2020 07:09:04 -0500 Subject: [PATCH 05/55] Minor fix to filename --- Notes/03_Program_organization/01_Script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ... From be34a7bc2f314919fd04c0463d68c2bbb32f060a Mon Sep 17 00:00:00 2001 From: David Beazley Date: Tue, 30 Jun 2020 09:32:22 -0500 Subject: [PATCH 06/55] Fix typo --- Notes/02_Working_with_data/01_Datatypes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 } >>> ``` From ced01f5373ec711c9ebf47d2ea556755c746aa0c Mon Sep 17 00:00:00 2001 From: Chad Bean Date: Wed, 1 Jul 2020 08:35:53 -0400 Subject: [PATCH 07/55] Fix syntax for inspecting imported numpy package --- Notes/09_Packages/02_Third_party.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Notes/09_Packages/02_Third_party.md b/Notes/09_Packages/02_Third_party.md index 2fa5e5508..94f236a45 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 >>> ``` From b8c570a6b7de0c070c397609f77b0433293107a5 Mon Sep 17 00:00:00 2001 From: caticoa3 Date: Wed, 1 Jul 2020 16:49:07 -0700 Subject: [PATCH 08/55] Update 03_Numbers.md The expected output does not match that of the correct solution, provided in morgage.py --- Notes/01_Introduction/03_Numbers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 202f07142..3f6013398 100644 --- a/Notes/01_Introduction/03_Numbers.md +++ b/Notes/01_Introduction/03_Numbers.md @@ -234,9 +234,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 ``` From 979a2e93281791bb168eb85394bd0f093b249d09 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Wed, 1 Jul 2020 19:33:03 -0500 Subject: [PATCH 09/55] Fixed output problem --- Notes/01_Introduction/03_Numbers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 202f07142..3f6013398 100644 --- a/Notes/01_Introduction/03_Numbers.md +++ b/Notes/01_Introduction/03_Numbers.md @@ -234,9 +234,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 ``` From 99aa5ae131103d41e349c33963ab25a56676071c Mon Sep 17 00:00:00 2001 From: bid0uille <48789037+bid0uille@users.noreply.github.com> Date: Thu, 2 Jul 2020 15:22:24 +0200 Subject: [PATCH 10/55] Fix missing new line Insert a newline at line 52 of 02.03 part. --- Notes/02_Working_with_data/03_Formatting.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Notes/02_Working_with_data/03_Formatting.md b/Notes/02_Working_with_data/03_Formatting.md index ae88c83b3..a3ec1e5f7 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) ``` From ee21b33e3fe80ee77db49e47f4baffa4502eeec4 Mon Sep 17 00:00:00 2001 From: bid0uille <48789037+bid0uille@users.noreply.github.com> Date: Thu, 2 Jul 2020 16:21:19 +0200 Subject: [PATCH 11/55] Fix missing word Word 'number' missing in 02.04 part. --- Notes/02_Working_with_data/04_Sequences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From b6a9aeae46f7450ca3756106e9a2a389bf75122b Mon Sep 17 00:00:00 2001 From: altvec Date: Thu, 2 Jul 2020 23:32:40 +0500 Subject: [PATCH 12/55] Fix missing new line --- Notes/04_Classes_objects/03_Special_methods.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From 58c9c3b5039a5c672b1e333df592cc557120b61c Mon Sep 17 00:00:00 2001 From: arf Date: Fri, 3 Jul 2020 23:04:35 +0200 Subject: [PATCH 13/55] fix typo in 02/07 line 14 'a~n~ list' --- Notes/02_Working_with_data/07_Objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ``` From 9eb78ddd9b1bc0a99af1c0bb3f4f3d55997af0d5 Mon Sep 17 00:00:00 2001 From: arf Date: Fri, 3 Jul 2020 23:15:09 +0200 Subject: [PATCH 14/55] fix missing word in 03/02 line 333 'Data/' --- Notes/03_Program_organization/02_More_functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/03_Program_organization/02_More_functions.md b/Notes/03_Program_organization/02_More_functions.md index 318ddc802..e7556aa72 100644 --- a/Notes/03_Program_organization/02_More_functions.md +++ b/Notes/03_Program_organization/02_More_functions.md @@ -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'}] >>> From c114f9e17bca467774e9019ef4479e6d12490cac Mon Sep 17 00:00:00 2001 From: bid0uille Date: Fri, 3 Jul 2020 23:38:23 +0200 Subject: [PATCH 15/55] fix missing word in 03/03 line 344 'is' --- Notes/03_Program_organization/03_Error_checking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/03_Program_organization/03_Error_checking.md b/Notes/03_Program_organization/03_Error_checking.md index f403507c0..d4e4779d4 100644 --- a/Notes/03_Program_organization/03_Error_checking.md +++ b/Notes/03_Program_organization/03_Error_checking.md @@ -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). From dc1f3b3aa11a3ff8d8b205ddcbdfdd0d34883337 Mon Sep 17 00:00:00 2001 From: bid0uille Date: Sat, 4 Jul 2020 00:04:28 +0200 Subject: [PATCH 16/55] fix sample output in 03/04 exercise 3.12 --- Notes/03_Program_organization/04_Modules.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Notes/03_Program_organization/04_Modules.md b/Notes/03_Program_organization/04_Modules.md index 260f715ca..22e7cf502 100644 --- a/Notes/03_Program_organization/04_Modules.md +++ b/Notes/03_Program_organization/04_Modules.md @@ -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 From 79ff2b3d579dd8dfd5a453d69d9f6c7cbcfb2e90 Mon Sep 17 00:00:00 2001 From: bid0uille Date: Sat, 4 Jul 2020 00:27:04 +0200 Subject: [PATCH 17/55] fix sample output in 03/05 exercises 3.15+16 --- .../03_Program_organization/05_Main_module.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) 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) From d6d00e527a24f797143cf3b85cfc183bac773d79 Mon Sep 17 00:00:00 2001 From: Gunnar Hermansson Date: Tue, 7 Jul 2020 09:30:09 +0200 Subject: [PATCH 18/55] Fixed typo and added a double space to line break rendered MarkDown. --- Notes/01_Introduction/03_Numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 3f6013398..80f4e0a10 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. From 9e054a0ec2ec390fc71b090fffb90f729503cdbd Mon Sep 17 00:00:00 2001 From: bid0uille <48789037+bid0uille@users.noreply.github.com> Date: Tue, 7 Jul 2020 22:44:14 +0200 Subject: [PATCH 19/55] fix typo in 09/02 line 124 was challange instead of challenge --- Notes/09_Packages/02_Third_party.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/09_Packages/02_Third_party.md b/Notes/09_Packages/02_Third_party.md index 94f236a45..2f1086cdd 100644 --- a/Notes/09_Packages/02_Third_party.md +++ b/Notes/09_Packages/02_Third_party.md @@ -121,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. From fc7f2a30c29fa611c5ff95a7f7122f701cc5e527 Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Wed, 29 Jul 2020 13:10:32 +0200 Subject: [PATCH 20/55] change wording in 03/02 since the file already exists --- Notes/03_Program_organization/02_More_functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/03_Program_organization/02_More_functions.md b/Notes/03_Program_organization/02_More_functions.md index e7556aa72..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 From f93493b28cb0fab06e7e3ddd4fc95cf54f5ac611 Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Mon, 3 Aug 2020 12:00:42 +0200 Subject: [PATCH 21/55] Typo --- Notes/04_Classes_objects/02_Inheritance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From 596d360f7b4b323c233a441f287db10e23eac8b9 Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Mon, 3 Aug 2020 16:40:38 +0200 Subject: [PATCH 22/55] fix indentation error --- Notes/05_Object_model/02_Classes_encapsulation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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): From 9e55e151e6d6ab50188919f4286e02e6d8b168b5 Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Tue, 4 Aug 2020 09:34:30 +0200 Subject: [PATCH 23/55] misplaced #statements in expanded for loop --- Notes/06_Generators/01_Iteration_protocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 9245991ffcd38476f8b4cf7e1754c2972075a4ad Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Wed, 5 Aug 2020 09:43:35 +0200 Subject: [PATCH 24/55] Add missing import to Ex6.8 --- Notes/06_Generators/03_Producers_consumers.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Notes/06_Generators/03_Producers_consumers.md b/Notes/06_Generators/03_Producers_consumers.md index ffd7845b5..eab64592b 100644 --- a/Notes/06_Generators/03_Producers_consumers.md +++ b/Notes/06_Generators/03_Producers_consumers.md @@ -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: From ff5368975ada41823c262b0229fc13fc74059c94 Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Thu, 6 Aug 2020 12:18:14 +0200 Subject: [PATCH 25/55] typo --- Notes/07_Advanced_Topics/03_Returning_functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/07_Advanced_Topics/03_Returning_functions.md b/Notes/07_Advanced_Topics/03_Returning_functions.md index 30e6f0772..896f8d593 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 From adb5c991abca91c9bbd38fafa9882d5cf0d2573e Mon Sep 17 00:00:00 2001 From: sina hosseinizad Date: Thu, 6 Aug 2020 12:46:03 +0200 Subject: [PATCH 26/55] add missing imports --- Notes/07_Advanced_Topics/03_Returning_functions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Notes/07_Advanced_Topics/03_Returning_functions.md b/Notes/07_Advanced_Topics/03_Returning_functions.md index 896f8d593..c5f1eb935 100644 --- a/Notes/07_Advanced_Topics/03_Returning_functions.md +++ b/Notes/07_Advanced_Topics/03_Returning_functions.md @@ -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() From 7d94852cdd4edf6904f8878c9f41bbf0ce9119de Mon Sep 17 00:00:00 2001 From: Zhi Li Date: Thu, 17 Sep 2020 09:46:30 -0400 Subject: [PATCH 27/55] Add missing link to built-in exceptions documentation --- Notes/03_Program_organization/03_Error_checking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/03_Program_organization/03_Error_checking.md b/Notes/03_Program_organization/03_Error_checking.md index d4e4779d4..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 From 9a3cd386fbef16bd3518c25dd8aa0e13e066739f Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 22 Nov 2020 13:20:19 -0600 Subject: [PATCH 28/55] Various typos fixed --- Notes/03_Program_organization/04_Modules.md | 4 ++-- Notes/06_Generators/03_Producers_consumers.md | 2 +- Notes/07_Advanced_Topics/03_Returning_functions.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Notes/03_Program_organization/04_Modules.md b/Notes/03_Program_organization/04_Modules.md index 22e7cf502..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 diff --git a/Notes/06_Generators/03_Producers_consumers.md b/Notes/06_Generators/03_Producers_consumers.md index ffd7845b5..3245e5559 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 ... ``` diff --git a/Notes/07_Advanced_Topics/03_Returning_functions.md b/Notes/07_Advanced_Topics/03_Returning_functions.md index 30e6f0772..896f8d593 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 From 8449211f7de422db8332cf1339057c040ff45825 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 22 Nov 2020 13:29:54 -0600 Subject: [PATCH 29/55] Added link --- Notes/00_Setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 3cfe6a2d752e828ad09b30be03d78d6860c37b11 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Thu, 24 Dec 2020 19:48:55 -0600 Subject: [PATCH 30/55] Fixed wording --- Notes/01_Introduction/03_Numbers.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Notes/01_Introduction/03_Numbers.md b/Notes/01_Introduction/03_Numbers.md index 80f4e0a10..c8cca87ef 100644 --- a/Notes/01_Introduction/03_Numbers.md +++ b/Notes/01_Introduction/03_Numbers.md @@ -220,7 +220,8 @@ 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 From c8dc52231a7a827b16218268765c472f31ae34d7 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 31 Jan 2021 19:38:29 -0600 Subject: [PATCH 31/55] Fixed typo --- Notes/02_Working_with_data/06_List_comprehension.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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' } >>> ``` From eca8be369b465e6e85f366643cb91b5f0ae6b1e8 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 28 Mar 2021 09:39:53 -0500 Subject: [PATCH 32/55] Fix typo --- Notes/02_Working_with_data/03_Formatting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Notes/02_Working_with_data/03_Formatting.md b/Notes/02_Working_with_data/03_Formatting.md index a3ec1e5f7..94b6198fe 100644 --- a/Notes/02_Working_with_data/03_Formatting.md +++ b/Notes/02_Working_with_data/03_Formatting.md @@ -115,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' >>> ``` From 92a8a73c078e7721d75fd0400e973b44bf7639b8 Mon Sep 17 00:00:00 2001 From: David Beazley Date: Sun, 28 Mar 2021 09:42:14 -0500 Subject: [PATCH 33/55] Added example --- Notes/02_Working_with_data/02_Containers.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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 From bbd7cbea34ad513bef9176d13777624cde256825 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Mon, 10 Jan 2022 14:02:11 +0100 Subject: [PATCH 34/55] Add first 3 solutions --- Work/bounce.py | 7 +++++++ Work/mortgage.py | 23 +++++++++++++++++++++++ Work/sears.py | 14 ++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 Work/sears.py 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..586df67db 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} {round(total_paid,2)} {round(principal,2)}') + + +print(f'Total paid: {total_paid} in {month} months') 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) From 28c44cf553a6cc31189ce06a16ed887db9ecbc30 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Mon, 10 Jan 2022 14:48:58 +0100 Subject: [PATCH 35/55] Use f-string formatting for float numbers --- Work/mortgage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Work/mortgage.py b/Work/mortgage.py index 586df67db..25cc35fd2 100644 --- a/Work/mortgage.py +++ b/Work/mortgage.py @@ -20,7 +20,7 @@ print(month) principal = principal * (1+rate/12) - payment - extra_payment total_paid = total_paid + payment - print(f'{month} {round(total_paid,2)} {round(principal,2)}') + print(f'{month} {total_paid:0.2f} {principal:0.2f}') print(f'Total paid: {total_paid} in {month} months') From fcb40e439194e8b3509ca5f34f968c7ac2cd30c7 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Mon, 10 Jan 2022 15:49:50 +0100 Subject: [PATCH 36/55] Add script to compute portfolio cost --- Work/pcost.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Work/pcost.py b/Work/pcost.py index e68aa20b4..87021bab3 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -1,3 +1,10 @@ -# pcost.py -# -# Exercise 1.27 +import csv + +total_cost = 0 + +with open('Data/portfolio.csv') as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + total_cost += int(row['shares']) * float(row['price']) + +print(f'Total cost {total_cost:0.2f}') From 94af6dfab7adb72b115a43c50a5c29a1692464c7 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Mon, 10 Jan 2022 16:23:41 +0100 Subject: [PATCH 37/55] Move computation of portfolio cost to a function --- Work/pcost.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Work/pcost.py b/Work/pcost.py index 87021bab3..698ad1261 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -1,10 +1,14 @@ import csv -total_cost = 0 +def portfolio_cost(filename): + """Read csv file with stock portfolio and compute the total cost""" + total_cost = 0 + with open('Data/portfolio.csv') as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + total_cost += int(row['shares']) * float(row['price']) + return total_cost -with open('Data/portfolio.csv') as csvfile: - reader = csv.DictReader(csvfile) - for row in reader: - total_cost += int(row['shares']) * float(row['price']) - -print(f'Total cost {total_cost:0.2f}') +if __name__ == '__main__': + cost = portfolio_cost('Data/portfolio.csv') + print(f'Total cost {cost:0.2f}') From a8ec716c932853e94901c5f4a860d6c80197e70b Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 10:56:58 +0100 Subject: [PATCH 38/55] Read filename from command line --- Work/pcost.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Work/pcost.py b/Work/pcost.py index 698ad1261..9f25c3e28 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -1,14 +1,20 @@ import csv +import sys def portfolio_cost(filename): """Read csv file with stock portfolio and compute the total cost""" total_cost = 0 - with open('Data/portfolio.csv') as csvfile: + with open(filename) as csvfile: reader = csv.DictReader(csvfile) for row in reader: total_cost += int(row['shares']) * float(row['price']) return total_cost if __name__ == '__main__': - cost = portfolio_cost('Data/portfolio.csv') + 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}') From 9012611043ec4b4d28e3632ee240d2d6790f7f00 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 10:57:22 +0100 Subject: [PATCH 39/55] Handle broken input with try/except Example to test: python pcost.py Data/missing.csv --- Work/pcost.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Work/pcost.py b/Work/pcost.py index 9f25c3e28..5830e34e6 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -7,7 +7,12 @@ def portfolio_cost(filename): with open(filename) as csvfile: reader = csv.DictReader(csvfile) for row in reader: - total_cost += int(row['shares']) * float(row['price']) + try: + total_cost += int(row['shares']) * float(row['price']) + except ValueError as err: + print(f'Invalid line at name {row["name"]}' + f'\nThe line is not used in the computation of Total cost' + f'\nErrormessage: {err}') return total_cost if __name__ == '__main__': From 9a615026c09ab914cfad323eb92d45ce7ca618d5 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 12:06:02 +0100 Subject: [PATCH 40/55] Exercise 2.4: Implement portfolio data structure --- Work/report.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Work/report.py b/Work/report.py index 47d5da7b1..48b3a5982 100644 --- a/Work/report.py +++ b/Work/report.py @@ -1,3 +1,44 @@ # report.py # # Exercise 2.4 +import csv +import sys + +def read_portfolio(filename): + """Read csv file with stock portfolio and return the list of stocks""" + portfolio = [] + with open(filename) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + try: + holding = (row['name'], int(row['shares']), float(row['price'])) + portfolio.append(holding) + except ValueError as err: + print(f'Invalid line at name {row["name"]}' + f'\nThe line is discarded' + f'\nErrormessage: {err}') + return portfolio + +def compute_total(portfolio): + """Compute total portfolio value + + portfolio: list of tuples containing stocks + in format (name, amount_shares, price) + + :return: total - total value as int + """ + total = 0.0 + for _, shares, price in portfolio: + total += shares*price + return total + +if __name__ == '__main__': + if len(sys.argv) == 2: + filename = sys.argv[1] + else: + filename = 'Data/portfolio.csv' + portfolio = read_portfolio(filename) + print(portfolio) + + total = compute_total(portfolio) + print(f'Total value of the portfolio: {total}$') From d9f388d1419c225aed30c9312c176043138bf832 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 13:04:09 +0100 Subject: [PATCH 41/55] Use dict as data structure for records --- Work/report.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Work/report.py b/Work/report.py index 48b3a5982..46d1f9b4c 100644 --- a/Work/report.py +++ b/Work/report.py @@ -11,8 +11,9 @@ def read_portfolio(filename): reader = csv.DictReader(csvfile) for row in reader: try: - holding = (row['name'], int(row['shares']), float(row['price'])) - portfolio.append(holding) + row['shares'] = int(row['shares']) + row['price'] = float(row['price']) + portfolio.append(row) except ValueError as err: print(f'Invalid line at name {row["name"]}' f'\nThe line is discarded' @@ -22,14 +23,14 @@ def read_portfolio(filename): def compute_total(portfolio): """Compute total portfolio value - portfolio: list of tuples containing stocks + portfolio: list of dicts containing stocks in format (name, amount_shares, price) :return: total - total value as int """ total = 0.0 - for _, shares, price in portfolio: - total += shares*price + for item in portfolio: + total += item['shares']*item['price'] return total if __name__ == '__main__': From d60e6fff9b8c4806c9abec3c1fb5c4edad092fe3 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 14:16:26 +0100 Subject: [PATCH 42/55] Pretty print the portfolio dictionary --- Work/report.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Work/report.py b/Work/report.py index 46d1f9b4c..ede2c315c 100644 --- a/Work/report.py +++ b/Work/report.py @@ -2,6 +2,7 @@ # # Exercise 2.4 import csv +from pprint import pprint import sys def read_portfolio(filename): @@ -39,7 +40,7 @@ def compute_total(portfolio): else: filename = 'Data/portfolio.csv' portfolio = read_portfolio(filename) - print(portfolio) + pprint(portfolio) total = compute_total(portfolio) print(f'Total value of the portfolio: {total}$') From a40a5f09f45f7837f521f880fde451b4152deef2 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 15:11:32 +0100 Subject: [PATCH 43/55] Read stock prices into a dictionary --- Work/report.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Work/report.py b/Work/report.py index ede2c315c..268e814d0 100644 --- a/Work/report.py +++ b/Work/report.py @@ -21,6 +21,20 @@ def read_portfolio(filename): 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'Row {i} does not have the right format\n' + f'Error message: {err}' + ) + return price_dict + def compute_total(portfolio): """Compute total portfolio value @@ -44,3 +58,6 @@ def compute_total(portfolio): total = compute_total(portfolio) print(f'Total value of the portfolio: {total}$') + + price_file = 'Data/prices.csv' + prices = read_prices(price_file) From d63249b40022580735d3c1e82413893dca81c527 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 21:41:19 +0100 Subject: [PATCH 44/55] Compute portfolio value using updated prices --- Work/report.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Work/report.py b/Work/report.py index 268e814d0..1b29567c1 100644 --- a/Work/report.py +++ b/Work/report.py @@ -35,17 +35,18 @@ def read_prices(filename): ) return price_dict -def compute_total(portfolio): - """Compute total portfolio value +def compute_value(portfolio, prices): + """Compute portfolio value - portfolio: list of dicts containing stocks - in format (name, amount_shares, price) + :input: portfolio: list of dicts containing stocks + in format (name, amount_shares, price) + prices: dictionary of price changes :return: total - total value as int """ total = 0.0 for item in portfolio: - total += item['shares']*item['price'] + total += item['shares'] * prices[item['name']] return total if __name__ == '__main__': @@ -56,8 +57,8 @@ def compute_total(portfolio): portfolio = read_portfolio(filename) pprint(portfolio) - total = compute_total(portfolio) - print(f'Total value of the portfolio: {total}$') - 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}') From 008e044bf7f474bede13ff082b2d2ea396e81e34 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 21:44:27 +0100 Subject: [PATCH 45/55] Improve formatting of exception --- Work/report.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Work/report.py b/Work/report.py index 1b29567c1..dec5d8aeb 100644 --- a/Work/report.py +++ b/Work/report.py @@ -30,8 +30,9 @@ def read_prices(filename): price_dict[row[0]] = float(row[1]) except IndexError as err: print( - f'Row {i} does not have the right format\n' - f'Error message: {err}' + f'\n\nread_prices():' + f'\nRow {i} does not have the right format' + f'\nError message: {err}\n' ) return price_dict From 9d9a32c48005d1e6d254de5a121eece64465ac2f Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Tue, 11 Jan 2022 22:19:24 +0100 Subject: [PATCH 46/55] Collect data to create portfolio table --- Work/report.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Work/report.py b/Work/report.py index dec5d8aeb..647c89e13 100644 --- a/Work/report.py +++ b/Work/report.py @@ -50,6 +50,25 @@ def compute_value(portfolio, prices): total += item['shares'] * prices[item['name']] return total +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 + + if __name__ == '__main__': if len(sys.argv) == 2: filename = sys.argv[1] @@ -63,3 +82,7 @@ def compute_value(portfolio, prices): portfolio_value = compute_value(portfolio, prices) print(f'Current value of the portfolio: ${portfolio_value}') + + report = make_report(portfolio, prices) + for r in report: + print(r) From 671554143131a6e76e968d993266bbf1e23c4458 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Wed, 12 Jan 2022 11:26:03 +0100 Subject: [PATCH 47/55] Add tabular formatting for report --- Work/report.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Work/report.py b/Work/report.py index 647c89e13..bc325cc52 100644 --- a/Work/report.py +++ b/Work/report.py @@ -84,5 +84,5 @@ def make_report(portfolio, prices): print(f'Current value of the portfolio: ${portfolio_value}') report = make_report(portfolio, prices) - for r in report: - print(r) + for name, shares, price, change in report: + print(f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}') From 1f14cd90ecfae0519a9f28d2dce5d6ca03333f6f Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Wed, 12 Jan 2022 14:01:02 +0100 Subject: [PATCH 48/55] Add header to the portfolio table --- Work/report.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Work/report.py b/Work/report.py index bc325cc52..3d068507d 100644 --- a/Work/report.py +++ b/Work/report.py @@ -68,6 +68,17 @@ def make_report(portfolio, prices): 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: + output += (f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}\n') + + print(output) + + if __name__ == '__main__': if len(sys.argv) == 2: @@ -84,5 +95,6 @@ def make_report(portfolio, prices): print(f'Current value of the portfolio: ${portfolio_value}') report = make_report(portfolio, prices) - for name, shares, price, change in report: - print(f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}') + + headers = ('Name', 'Shares', 'Price', 'Change') + print_report(report, headers) From 4fe3b20ed84343e67ffd620eac64fed6d43a1d66 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Wed, 12 Jan 2022 14:13:20 +0100 Subject: [PATCH 49/55] Prepend dollar sign to price column --- Work/report.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Work/report.py b/Work/report.py index 3d068507d..2d09d20c4 100644 --- a/Work/report.py +++ b/Work/report.py @@ -74,7 +74,8 @@ def print_report(report, header): l = ''.join(['{:_<10} '.format('') for i in range(4)]) output = f'{h}\n{l}\n' for name, shares, price, change in report: - output += (f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}\n') + price_in_dollar = f'${price:.2f}' + output += (f'{name:>10s} {shares:>10d} {price_in_dollar:>10} {change:>10.2f}\n') print(output) From 0a3ef3440df68539485670c338bcf31e3bcbce3a Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Wed, 12 Jan 2022 14:42:16 +0100 Subject: [PATCH 50/55] Use enumerate in iteration to allow showing broken row nr --- Work/pcost.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Work/pcost.py b/Work/pcost.py index 5830e34e6..edcf077e8 100644 --- a/Work/pcost.py +++ b/Work/pcost.py @@ -6,11 +6,11 @@ def portfolio_cost(filename): total_cost = 0 with open(filename) as csvfile: reader = csv.DictReader(csvfile) - for row in reader: + for rowno, row in enumerate(reader): try: total_cost += int(row['shares']) * float(row['price']) except ValueError as err: - print(f'Invalid line at name {row["name"]}' + 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 From 21ab8106bcdc51f6f4c975104bdee267940db561 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Thu, 13 Jan 2022 12:49:52 +0100 Subject: [PATCH 51/55] Compute total as sequence reduction --- Work/report.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Work/report.py b/Work/report.py index 2d09d20c4..1b99dc120 100644 --- a/Work/report.py +++ b/Work/report.py @@ -45,10 +45,11 @@ def compute_value(portfolio, prices): :return: total - total value as int """ - total = 0.0 - for item in portfolio: - total += item['shares'] * prices[item['name']] - return total + + # 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 From 6ebb35b6d8305cba329836590c3f093013c6f0ec Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Thu, 13 Jan 2022 12:51:10 +0100 Subject: [PATCH 52/55] Refactor read_portfolio use csv.reader instead of dict reader to be able to follow along the coming chapters --- Work/report.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Work/report.py b/Work/report.py index 1b99dc120..ed9a00aa0 100644 --- a/Work/report.py +++ b/Work/report.py @@ -9,12 +9,21 @@ def read_portfolio(filename): """Read csv file with stock portfolio and return the list of stocks""" portfolio = [] with open(filename) as csvfile: - reader = csv.DictReader(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 + types = [str, int, float] + indices = [ headers.index(colname) for colname in select ] + for row in reader: try: - row['shares'] = int(row['shares']) - row['price'] = float(row['price']) - portfolio.append(row) + # dict-comprehension + record = { colname: row[index] for colname, index in zip(select, indices) } + record['shares'] = int(record['shares']) + record['price'] = float(record['price']) + portfolio.append(record) except ValueError as err: print(f'Invalid line at name {row["name"]}' f'\nThe line is discarded' From 0fc347b7dd9feff51327f8ab2b60ee598dcc7703 Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Thu, 13 Jan 2022 14:17:11 +0100 Subject: [PATCH 53/55] Add flexible type conversion to script --- Work/report.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Work/report.py b/Work/report.py index ed9a00aa0..6807e8761 100644 --- a/Work/report.py +++ b/Work/report.py @@ -5,6 +5,24 @@ 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): """Read csv file with stock portfolio and return the list of stocks""" portfolio = [] @@ -14,15 +32,13 @@ def read_portfolio(filename): # Fill select with field names if you only want a subset of the data # For now we take all select = headers - types = [str, int, float] + type_list = [str, int, float] 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) } - record['shares'] = int(record['shares']) - record['price'] = float(record['price']) portfolio.append(record) except ValueError as err: print(f'Invalid line at name {row["name"]}' From ed41542d3beb11b43ef26ef7b5fed33db17283fe Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Thu, 13 Jan 2022 14:24:51 +0100 Subject: [PATCH 54/55] Do all processing in one complicated dict comprehension --- Work/report.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Work/report.py b/Work/report.py index 6807e8761..c8a385c0e 100644 --- a/Work/report.py +++ b/Work/report.py @@ -38,7 +38,9 @@ def read_portfolio(filename): try: row = type_conversion(type_list, row) # dict-comprehension - record = { colname: row[index] for colname, index in zip(select, indices) } + # 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"]}' From 4a4cad4826f773bc50575005a42da0a067487fcf Mon Sep 17 00:00:00 2001 From: Stephan Klinger Date: Thu, 13 Jan 2022 14:56:42 +0100 Subject: [PATCH 55/55] Make the read_portfolio function work for any input file --- Work/report.py | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Work/report.py b/Work/report.py index c8a385c0e..c8405c074 100644 --- a/Work/report.py +++ b/Work/report.py @@ -23,7 +23,7 @@ def type_conversion(type_list, row): converted = [func(val) for func, val in type_row] return converted -def read_portfolio(filename): +def read_portfolio(filename, type_list=[]): """Read csv file with stock portfolio and return the list of stocks""" portfolio = [] with open(filename) as csvfile: @@ -32,7 +32,6 @@ def read_portfolio(filename): # Fill select with field names if you only want a subset of the data # For now we take all select = headers - type_list = [str, int, float] indices = [ headers.index(colname) for colname in select ] for row in reader: try: @@ -111,19 +110,30 @@ def print_report(report, header): if __name__ == '__main__': if len(sys.argv) == 2: - filename = sys.argv[1] + 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 = 'Data/portfolio.csv' - portfolio = read_portfolio(filename) + filename = param + portfolio = read_portfolio(filename, type_list) pprint(portfolio) - price_file = 'Data/prices.csv' - prices = read_prices(price_file) + # 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}') + portfolio_value = compute_value(portfolio, prices) + print(f'Current value of the portfolio: ${portfolio_value}') - report = make_report(portfolio, prices) + report = make_report(portfolio, prices) - headers = ('Name', 'Shares', 'Price', 'Change') - print_report(report, headers) + headers = ('Name', 'Shares', 'Price', 'Change') + print_report(report, headers)