From f9717a12c62227a783bd22965e5d0a007f93d17e Mon Sep 17 00:00:00 2001 From: David Beazley Date: Wed, 27 May 2020 21:13:24 -0500 Subject: [PATCH] Editing --- Notes/01_Introduction/04_Strings.md | 9 ++++ Notes/01_Introduction/05_Lists.md | 59 +++++++++++--------- Notes/01_Introduction/06_Files.md | 78 +++++++++++++++------------ Notes/01_Introduction/07_Functions.md | 37 ++++++++----- Solutions/{1_32 => 1_33}/pcost.py | 0 5 files changed, 110 insertions(+), 73 deletions(-) rename Solutions/{1_32 => 1_33}/pcost.py (100%) diff --git a/Notes/01_Introduction/04_Strings.md b/Notes/01_Introduction/04_Strings.md index 1184634..4ed8310 100644 --- a/Notes/01_Introduction/04_Strings.md +++ b/Notes/01_Introduction/04_Strings.md @@ -326,6 +326,15 @@ Oops! That's not what you wanted. Fix it so that the `symbols` variable holds t >>> ``` +Add `'HPQ'` to the front the string: + +```python +>>> symbols = ? +>>> symbols +'HPQ,AAPL,IBM,MSFT,YHOO,SCO,GOOG' +>>> +``` + In these examples, it might look like the original string is being modified, in an apparent violation of strings being read only. Not so. Operations on strings create an entirely new string each diff --git a/Notes/01_Introduction/05_Lists.md b/Notes/01_Introduction/05_Lists.md index d0bc0aa..cae220d 100644 --- a/Notes/01_Introduction/05_Lists.md +++ b/Notes/01_Introduction/05_Lists.md @@ -1,8 +1,12 @@ +[Contents](../Contents) \| [Previous (1.4 Strings)](04_Strings) \| [Next (1.6 Files)](06_Files) + # 1.5 Lists +This section introduces lists, Python's primary type for holding an ordered collection of values. + ### Creating a List -Use square brackets to define a list: +Use square brackets to define a list literal: ```python names = [ 'Elwood', 'Jake', 'Curtis' ] @@ -12,7 +16,7 @@ nums = [ 39, 38, 42, 65, 111] Sometimes lists are created by other methods. For example, a string can be split into a list using the `split()` method: -```pycon +```python >>> line = 'GOOG,100,490.10' >>> row = line.split(',') >>> row @@ -53,7 +57,7 @@ Negative indices count from the end. names[-1] # 'Curtis' ``` -You can change any item in the list. +You can change any item in a list. ```python names[1] = 'Joliet Jake' @@ -83,7 +87,7 @@ s * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3] ### List Iteration and Search -Iterating over the list contents. +Use `for` to iterate over the list contents. ```python for name in names: @@ -117,8 +121,9 @@ names.remove('Curtis') del names[1] ``` -Removing an item does not create a hole. Other items will move down to fill the space vacated. -If there are more than one occurrence of the element, `.remove()` will remove only the first occurrence. +Removing an item does not create a hole. Other items will move down +to fill the space vacated. If there are more than one occurrence of +the element, `remove()` will remove only the first occurrence. ### List Sorting @@ -137,11 +142,17 @@ s = ['foo', 'bar', 'spam'] s.sort() # ['bar', 'foo', 'spam'] ``` +Use `sorted()` if you'd like to make a new list instead: + +```python +t = sorted(s) # s unchanged, t holds sorted values +``` + ### Lists and Math *Caution: Lists were not designed for math operations.* -```pycon +```python >>> nums = [1, 2, 3, 4, 5] >>> nums * 2 [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] @@ -149,7 +160,7 @@ s.sort() # ['bar', 'foo', 'spam'] [1, 2, 3, 4, 5, 10, 11, 12, 13, 14] >>> ``` -Specifically, lists don't represent vectors/matrices as in MATLAB, Octave, IDL, etc. +Specifically, lists don't represent vectors/matrices as in MATLAB, Octave, R, etc. However, there are some packages to help you with that (e.g. [numpy](https://numpy.org)). ## Exercises @@ -157,13 +168,13 @@ However, there are some packages to help you with that (e.g. [numpy](https://num In this exercise, we experiment with Python's list datatype. In the last section, you worked with strings containing stock symbols. -```pycon +```python >>> symbols = 'HPQ,AAPL,IBM,MSFT,YHOO,DOA,GOOG' ``` Split it into a list of names using the `split()` operation of strings: -```pycon +```python >>> symlist = symbols.split(',') ``` @@ -228,7 +239,7 @@ For instance, in the above example, the last two items of `symlist` got replaced The `for` loop works by looping over data in a sequence such as a list. Check this out by typing the following loop and watching what happens: -```pycon +```python >>> for s in symlist: print('s =', s) # Look at the output @@ -238,7 +249,7 @@ Check this out by typing the following loop and watching what happens: Use the `in` or `not in` operator to check if `'AIG'`,`'AA'`, and `'CAT'` are in the list of symbols. -```pycon +```python >>> # Is 'AIG' IN the `symlist`? True >>> # Is 'AA' IN the `symlist`? @@ -252,7 +263,7 @@ True Use the `append()` method to add the symbol `'RHT'` to end of `symlist`. -```pycon +```python >>> # append 'RHT' >>> symlist ['HPQ', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'GOOG', 'RHT'] @@ -261,7 +272,7 @@ Use the `append()` method to add the symbol `'RHT'` to end of `symlist`. Use the `insert()` method to insert the symbol `'AA'` as the second item in the list. -```pycon +```python >>> # Insert 'AA' as the second item in the list >>> symlist ['HPQ', 'AA', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'GOOG', 'RHT'] @@ -270,7 +281,7 @@ Use the `insert()` method to insert the symbol `'AA'` as the second item in the Use the `remove()` method to remove `'MSFT'` from the list. -```pycon +```python >>> # Remove 'MSFT' >>> symlist ['HPQ', 'AA', 'AAPL', 'AIG', 'YHOO', 'GOOG', 'RHT'] @@ -281,7 +292,7 @@ Append a duplicate entry for `'YHOO'` at the end of the list. *Note: it is perfectly fine for a list to have duplicate values.* -```pycon +```python >>> # Append 'YHOO' >>> symlist ['HPQ', 'AA', 'AAPL', 'AIG', 'YHOO', 'GOOG', 'RHT', 'YHOO'] @@ -290,7 +301,7 @@ Append a duplicate entry for `'YHOO'` at the end of the list. Use the `index()` method to find the first position of `'YHOO'` in the list. -```pycon +```python >>> # Find the first index of 'YHOO' 4 >>> symlist[4] @@ -300,7 +311,7 @@ Use the `index()` method to find the first position of `'YHOO'` in the list. Count how many times `'YHOO'` is in the list: -```pycon +```python >>> symlist.count('YHOO') 2 >>> @@ -308,7 +319,7 @@ Count how many times `'YHOO'` is in the list: Remove the first occurrence of `'YHOO'`. -```pycon +```python >>> # Remove first occurrence 'YHOO' >>> symlist ['HPQ', 'AA', 'AAPL', 'AIG', 'GOOG', 'RHT', 'YHOO'] @@ -322,7 +333,7 @@ However, we'll see an elegant way to do this in section 2. Want to sort a list? Use the `sort()` method. Try it out: -```pycon +```python >>> symlist.sort() >>> symlist ['AA', 'AAPL', 'AIG', 'GOOG', 'HPQ', 'RHT', 'YHOO'] @@ -331,7 +342,7 @@ Want to sort a list? Use the `sort()` method. Try it out: Want to sort in reverse? Try this: -```pycon +```python >>> symlist.sort(reverse=True) >>> symlist ['YHOO', 'RHT', 'HPQ', 'GOOG', 'AIG', 'AAPL', 'AA'] @@ -345,7 +356,7 @@ Note: Sorting a list modifies its contents 'in-place'. That is, the elements of Want to take a list of strings and join them together into one string? Use the `join()` method of strings like this (note: this looks funny at first). -```pycon +```python >>> a = ','.join(symlist) >>> a 'YHOO,RHT,HPQ,GOOG,AIG,AAPL,AA' @@ -363,7 +374,7 @@ Use the `join()` method of strings like this (note: this looks funny at first). Lists can contain any kind of object, including other lists (e.g., nested lists). Try this out: -```pycon +```python >>> nums = [101, 102, 103] >>> items = ['spam', symlist, nums] >>> items @@ -375,7 +386,7 @@ The first element is a string, but the other two elements are lists. You can access items in the nested lists by using multiple indexing operations. -```pycon +```python >>> items[0] 'spam' >>> items[0][0] diff --git a/Notes/01_Introduction/06_Files.md b/Notes/01_Introduction/06_Files.md index c1368f2..2edb98c 100644 --- a/Notes/01_Introduction/06_Files.md +++ b/Notes/01_Introduction/06_Files.md @@ -1,5 +1,9 @@ +[Contents](../Contents) \| [Previous (1.5 Lists)](05_Lists) \| [Next (1.7 Functions)](07_Functions) + # 1.6 File Management +Most programs need to read input from somewhere. This section discusses file access. + ### File Input and Output Open a file. @@ -9,7 +13,7 @@ f = open('foo.txt', 'rt') # Open for reading (text) g = open('bar.txt', 'wt') # Open for writing (text) ``` -Reading data. +Read all of the data. ```python data = f.read() @@ -18,7 +22,7 @@ data = f.read() data = f.read([maxbytes]) ``` -Writing text to a file. +Write some text. ```python g.write('some text') @@ -31,11 +35,12 @@ f.close() g.close() ``` -Files should be properly closed. This is why the preferred approach is to use the `with` statement. +Files should be properly closed and it's an easy step to forget. +Thus, the preferred approach is to use the `with` statement like this. ```python -with open(filename, 'rt') as f: - # Use the file `f` +with open(filename, 'rt') as file: + # Use the file `file` ... # No need to close explicitly ...statements @@ -45,61 +50,63 @@ This automatically closes the file when control leaves the indented code block. ### Common Idioms for Reading File Data -Reading an entire file all at once as a string. +Read an entire file all at once as a string. ```python -with open('foo.txt', 'rt') as f: - data = f.read() +with open('foo.txt', 'rt') as file: + data = file.read() # `data` is a string with all the text in `foo.txt` ``` -Reading a file line-by-line +Read a file line-by-line by iterating. ```python -with open(filename, 'rt') as f: - for line in f: - # Process the line `f` +with open(filename, 'rt') as file: + for line in file: + # Process the line ``` -Writing string data. +### Common Idioms for Write to a File + +Write string data. ```python -with open('outfile', 'wt') as f: - f.write('Hello World\n') +with open('outfile', 'wt') as out: + out.write('Hello World\n') ... ``` -Redirecting the print function. +Redirect the print function. ```python -with open('outfile', 'wt') as f: - print('Hello World', file=f) +with open('outfile', 'wt') as out: + print('Hello World', file=out) ... ``` ## Exercises -This exercise depends on a file `Data/portfolio.csv`. The file contains a list of lines with information on a portfolio of stocks. -Locate the file and look at its contents: +These exercises depend on a file `Data/portfolio.csv`. The file +contains a list of lines with information on a portfolio of stocks. +It is assumed that you are working in the `practical-python/Work/` +directory. If you're not sure, you can find out where Python thinks +it's running by doing this: -### Exercise 1.26: File Preliminaries - -*Note: Make sure you are running Python in a location where you can access the `portfolio.csv` file. -It's normally located in `Data/portfolio.csv`. -You can find out where Python thinks it's running by doing this: - -```pycon +```python >>> import os >>> os.getcwd() -'/Users/beazley/Desktop/practical-python' # Output vary +'/Users/beazley/Desktop/practical-python/Work' # Output vary >>> ``` +### Exercise 1.26: File Preliminaries + First, try reading the entire file all at once as a big string: -```pycon +```python >>> with open('Data/portfolio.csv', 'rt') as f: data = f.read() + >>> data 'name,shares,price\n"AA",100,32.20\n"IBM",50,91.10\n"CAT",150,83.44\n"MSFT",200,51.23\n"GE",95,40.37\n"MSFT",50,65.10\n"IBM",100,70.44\n' >>> print(data) @@ -127,10 +134,11 @@ time. To read a file line-by-line, use a for-loop like this: -```pycon +```python >>> with open('Data/portfolio.csv', 'rt') as f: for line in f: print(line, end='') + name,shares,price "AA",100,32.20 "IBM",50,91.10 @@ -145,7 +153,7 @@ On certain occasions, you might want to manually read or skip a *single* line of text (e.g., perhaps you want to skip the first line of column headers). -```pycon +```python >>> f = open('Data/portfolio.csv', 'rt') >>> headers = next(f) >>> headers @@ -167,7 +175,7 @@ Thus, you normally wouldn’t call it directly unless you’re trying to explici Once you’re reading lines of a file, you can start to perform more processing such as splitting. For example, try this: -```pycon +```python >>> f = open('Data/portfolio.csv', 'rt') >>> headers = next(f).split(',') >>> headers @@ -189,7 +197,7 @@ For example, try this: Now that you know how to read a file, let’s write a program to perform a simple calculation. The columns in `portfolio.csv` correspond to the stock name, number of -shares, and purchase price of a single share. Write a program called +shares, and purchase price of a single stock holding. Write a program called `pcost.py` that opens this file, reads all lines, and calculates how much it cost to purchase all of the shares in the portfolio. @@ -201,7 +209,7 @@ Your program should print output such as the following: Total cost 44671.15 ``` -### Exercise 1.28: Other kinds of 'files' +### Exercise 1.28: Other kinds of "files" What if you wanted to read a non-text file such as a gzip-compressed datafile? The builtin `open()` function won’t help you here, but @@ -210,7 +218,7 @@ files. Try it: -```pycon +```python >>> import gzip >>> with gzip.open('Data/portfolio.csv.gz') as f: for line in f: diff --git a/Notes/01_Introduction/07_Functions.md b/Notes/01_Introduction/07_Functions.md index f207508..958fae9 100644 --- a/Notes/01_Introduction/07_Functions.md +++ b/Notes/01_Introduction/07_Functions.md @@ -1,7 +1,9 @@ +[Contents](../Contents) \| [Previous (1.6 Files)](06_Files) \| [Next (2.0 Working with Data)](../02_Working_with_data/00_Overview) + # 1.7 Functions As your programs start to get larger, you'll want to get organized. This section -introduces functions. Error handling with exceptions is also introduced. +briefly introduces functions and library modules. Error handling with exceptions is also introduced. ### Custom Functions @@ -19,10 +21,9 @@ def sumcount(n): return total ``` -Calling a function. +To call a function. ```python -# Use parenthesis to call the function a = sumcount(100) ``` @@ -33,13 +34,12 @@ The `return` keyword is needed to explicitly specify the return value of the fun Python comes with a large standard library. Library modules are accessed using `import`. +For example: ```python -# `math` module import math x = math.sqrt(10) -# `urllib.request` module import urllib.request u = urllib.request.urlopen('http://www.python.org/') data = u.read() @@ -49,11 +49,12 @@ We will cover libraries and modules in more detail later. ### Errors and exceptions -Functions report errors as exceptions. An exception causes the program to stop. +Functions report errors as exceptions. An exception causes a function to abort and may +cause your entire program to stop if unhandled. Try this in your python REPL. -```pycon +```python >>> int('N/A') Traceback (most recent call last): File "", line 1, in @@ -82,6 +83,12 @@ for line in f: The name `ValueError` must match the kind of error you are trying to catch. +It is often difficult to know exactly what kinds of errors might occur +in advance depending on the operation being performed. For better or +for worse, exception handling often gets added *after* a program has +unexpectedly crashed (i.e., "oh, we forgot to catch that error. We +should handle that!"). + ### Raising Exceptions To raise an exception, use the `raise` statement. @@ -104,7 +111,7 @@ RuntimeError: What a kerfuffle ### Exercise 1.29: Defining a function -You can define a simple function using the `def` statement. For example, +Try defining a simple function: ```python >>> def greeting(name): @@ -124,7 +131,7 @@ Try typing a command such as `help(greeting)` to see it displayed. ### Exercise 1.30: Turning a script into a function Take the code you wrote for the `pcost.py` program in [Exercise 1.27](06_Files) -and turn it into a function `portfolio_cost(filename)`. The +and turn it into a function `portfolio_cost(filename)`. This function takes a filename as input, reads the portfolio data in that file, and returns the total cost of the portfolio as a float. @@ -160,9 +167,11 @@ This will allow you to call your function from the interactive mode. Being able to experiment with your code interactively is useful for testing and debugging. +### Exercise 1.31: Error handling + What happens if you try your function on a file with some missing fields? -```pycon +```python >>> portfolio_cost('Data/missing.csv') Traceback (most recent call last): File "", line 1, in @@ -180,14 +189,14 @@ manner. Modify the `pcost.py` program to catch the exception, print a warning message, and continue processing the rest of the file. -### Exercise 1.31: Using a library function +### Exercise 1.32: Using a library function Python comes with a large standard library of useful functions. One library that might be useful here is the `csv` module. You should use it whenever you have to work with CSV data files. Here is an example of how it works: -```pycon +```python >>> import csv >>> f = open('Data/portfolio.csv') >>> rows = csv.reader(f) @@ -216,7 +225,7 @@ away from the names in the first column. Modify your `pcost.py` program so that it uses the `csv` module for parsing and try running earlier examples. -### Exercise 1.32: Reading from the command line +### Exercise 1.33: Reading from the command line In the `pcost.py` program, the name of the input file has been hardwired into the code: @@ -250,7 +259,7 @@ def portfolio_cost(filename): if len(sys.argv) == 2: filename = sys.argv[1] else: - filename = 'portfolio.csv' + filename = 'Data/portfolio.csv' cost = portfolio_cost(filename) print('Total cost:', cost) diff --git a/Solutions/1_32/pcost.py b/Solutions/1_33/pcost.py similarity index 100% rename from Solutions/1_32/pcost.py rename to Solutions/1_33/pcost.py