From 45c7ec1f4a2cca8e85074eedaa6c32f82c9b9f2e Mon Sep 17 00:00:00 2001 From: David Beazley Date: Tue, 26 May 2020 15:30:14 -0500 Subject: [PATCH] Links and renumbering --- Notes/04_Classes_objects/01_Class.md | 8 ++++---- Notes/04_Classes_objects/02_Inheritance.md | 10 +++++----- Notes/04_Classes_objects/03_Special_methods.md | 9 +++++---- .../04_Classes_objects/04_Defining_exceptions.md | 4 +++- Notes/05_Object_model/01_Dicts_revisited.md | 15 ++++++++------- Notes/05_Object_model/02_Classes_encapsulation.md | 8 +++++--- Notes/06_Generators/01_Iteration_protocol.md | 8 ++++---- Notes/06_Generators/02_Customizing_iteration.md | 10 +++++----- Notes/06_Generators/03_Producers_consumers.md | 12 ++++++------ Notes/06_Generators/04_More_generators.md | 7 ++++--- 10 files changed, 49 insertions(+), 42 deletions(-) diff --git a/Notes/04_Classes_objects/01_Class.md b/Notes/04_Classes_objects/01_Class.md index 97e7222..ee47617 100644 --- a/Notes/04_Classes_objects/01_Class.md +++ b/Notes/04_Classes_objects/01_Class.md @@ -110,7 +110,7 @@ If you want to operate on an instance, you always have to refer too it explicitl ## Exercises -### (a) Objects as Data Structures +### Exercise 4.1: Objects as Data Structures In section 2 and 3, we worked with data represented as tuples and dictionaries. For example, a holding of stock could be represented as a tuple like this: @@ -182,7 +182,7 @@ dictionary, just with somewhat different syntax. For example, instead of writing `s['name']` or `s['price']`, you now write `s.name` and `s.price`. -### (b) Reading Data into a List of Objects +### Exercise 4.2: Reading Data into a List of Objects In your `stock.py` program, write a function `read_portfolio(filename)` that reads portfolio data from a file into @@ -226,7 +226,7 @@ Try a list comprehension: Again, notice the similarity between `Stock` objects and dictionaries. They’re basically the same idea, but the syntax for accessing values differs. -### (c) Adding some Methods +### Exercise 4.3: Adding some Methods With classes, you can attach functions to your objects. These are known as methods and are functions that operate on the data stored @@ -250,4 +250,4 @@ work like this: >>> ``` -[Next](02_Inheritance) \ No newline at end of file +[Contents](../Contents) \| [Previous (3.6 Design discussion)](../03_Program_organization/06_Design_discussion) \| [Next (4.2 Inheritance)](02_Inheritance) diff --git a/Notes/04_Classes_objects/02_Inheritance.md b/Notes/04_Classes_objects/02_Inheritance.md index 911e5e3..59fae09 100644 --- a/Notes/04_Classes_objects/02_Inheritance.md +++ b/Notes/04_Classes_objects/02_Inheritance.md @@ -220,7 +220,7 @@ We're not going to explore multiple inheritance further in this course. ## Exercises -### (a) Print Portfolio +### Exercise 4.4: Print Portfolio A major use of inheritance is in writing code that’s meant to be extended or customized in various ways—especially in libraries or frameworks. To illustrate, start by adding the following function to your `stock.py` program: @@ -263,7 +263,7 @@ When you run your `stock.py`, you should get this output: IBM 100 70.44 ``` -### (b) An Extensibility Problem +### Exercise 4.5: An Extensibility Problem Suppose that you wanted to modify the `print_portfolio()` function to support a variety of different output formats such as plain-text, @@ -329,7 +329,7 @@ if __name__ == '__main__': When you run this new code, your program will immediately crash with a `NotImplementedError` exception. That’s not too exciting, but continue to the next part. -### (c) Using Inheritance to Produce Different Output +### Exercise 4.6: Using Inheritance to Produce Different Output The `TableFormatter` class you defined in part (a) is meant to be extended via inheritance. In fact, that’s the whole idea. To illustrate, define a class `TextTableFormatter` like this: @@ -430,7 +430,7 @@ Using a similar idea, define a class `HTMLTableFormatter` that produces a table Test your code by modifying the main program to create a `HTMLTableFormatter` object instead of a `CSVTableFormatter` object. -### (d) Polymorphism in Action +### Exercise 4.7: Polymorphism in Action A major feature of object-oriented programming is that you can plug an object into a program and it will work without having to change any of @@ -499,4 +499,4 @@ That said, understanding what happened in this exercise will take you pretty far in terms of using most library modules and knowing what inheritance is good for (extensibility). -[Next](03_Special_methods) +[Contents](../Contents) \| [Previous (4.1 Classes)](01_Class) \| [Next (4.3 Special methods)](03_Special_methods) diff --git a/Notes/04_Classes_objects/03_Special_methods.md b/Notes/04_Classes_objects/03_Special_methods.md index cdbc7fe..9b98626 100644 --- a/Notes/04_Classes_objects/03_Special_methods.md +++ b/Notes/04_Classes_objects/03_Special_methods.md @@ -202,7 +202,7 @@ x = getattr(obj, 'x', None) ## Exercises -### (a) Better output for printing objects +### Exercise 4.8: Better output for printing objects All Python objects have two string representations. The first representation is created by string conversion via `str()` (which is @@ -248,7 +248,7 @@ See what happens when you read a portfolio of stocks and view the resulting list >>> ``` -### (b) An example of using `getattr()` +### Exercise 4.9: An example of using `getattr()` In Exercise 4.2 you worked with a function `print_portfolio()` that made a table for a stock portfolio. That function was hard-coded to only work with stock data—-how limiting! You can do so much more if you use functions such as `getattr()`. @@ -306,7 +306,7 @@ format. Here’s how it should work: >>> ``` -### (c) Exercise Bonus: Column Formatting +### Exercise 4.10: Exercise Bonus: Column Formatting Modify the `print_table()` function in part (B) so that it also accepts a list of format specifiers for formatting the contents of @@ -329,4 +329,5 @@ each column. >>> ``` -[Next](04_Defining_exceptions) +[Contents](../Contents) \| [Previous (4.2 Inheritance)](02_Inheritance) \| [Next (4.4 Exceptions)](04_Defining_exceptions) + diff --git a/Notes/04_Classes_objects/04_Defining_exceptions.md b/Notes/04_Classes_objects/04_Defining_exceptions.md index 0c31365..a235fe9 100644 --- a/Notes/04_Classes_objects/04_Defining_exceptions.md +++ b/Notes/04_Classes_objects/04_Defining_exceptions.md @@ -22,7 +22,7 @@ class ProtocolError(NetworkError): ## Exercises -### (a) Defining a custom exception +### Exercise 4.11: Defining a custom exception It is often good practice for libraries to define their own exceptions. @@ -47,3 +47,5 @@ Traceback (most recent call last): FormatError: Unknown table format xls >>> ``` + +[Contents](../Contents) \| [Previous (4.3 Special methods)](03_Special_methods) \| [Next (5 Object Model)](../05_Object_model/00_Overview) diff --git a/Notes/05_Object_model/01_Dicts_revisited.md b/Notes/05_Object_model/01_Dicts_revisited.md index 340c298..157edf1 100644 --- a/Notes/05_Object_model/01_Dicts_revisited.md +++ b/Notes/05_Object_model/01_Dicts_revisited.md @@ -362,10 +362,10 @@ Frameworks / libraries sometimes use it for advanced features involving composit ## Exercises -In Exercise 4.1, you defined a class `Stock` that represented a holding of stock. +In Section 4, you defined a class `Stock` that represented a holding of stock. In this exercise, we will use that class. -### (a) Representation of Instances +### Exercise 5.1: Representation of Instances At the interactive shell, inspect the underlying dictionaries of the two instances you created: @@ -380,7 +380,7 @@ At the interactive shell, inspect the underlying dictionaries of the two instanc >>> ``` -### (b) Modification of Instance Data +### Exercise 5.2: Modification of Instance Data Try setting a new attribute on one of the above instances: @@ -412,7 +412,7 @@ top of a dictionary. *Note: it should be emphasized that direct manipulation of the dictionary is uncommon—you should always write your code to use the (.) syntax.* -### (c) The role of classes +### Exercise 5.3: The role of classes The definitions that make up a class definition are shared by all instances of that class. Notice, that all instances have a link back to their associated class: @@ -517,7 +517,7 @@ It is shared by all of the instances that get created. >>> ``` -### (d) Bound Methods +### Exercise 5.4: Bound Methods A subtle feature of Python is that invoking a method actually involves two steps and something known as a bound method. @@ -568,7 +568,7 @@ For example, calling `s(25)` actually does this: >>> ``` -### (e) Inheritance +### Exercise 5.5: Inheritance Make a new class that inherits from `Stock`. @@ -617,4 +617,5 @@ Here’s how the `cost()` method of instance `n` above would be found: >>> ``` -[Next](02_Classes_encapsulation) \ No newline at end of file +[Contents](../Contents) \| [Previous (4.4 Exceptions)](../04_Classes_objects/04_Defining_exceptions) \| [Next (5.2 Encapsulation)](02_Classes_encapsulation) + diff --git a/Notes/05_Object_model/02_Classes_encapsulation.md b/Notes/05_Object_model/02_Classes_encapsulation.md index e0b68d9..01db948 100644 --- a/Notes/05_Object_model/02_Classes_encapsulation.md +++ b/Notes/05_Object_model/02_Classes_encapsulation.md @@ -252,7 +252,7 @@ day-to-day coding. ## Exercises -### (a) Simple properties +### Exercise 5.6: Simple properties Properties are a useful way to add "computed attributes" to an object. In Exercise 4.1, you created an object `Stock`. Notice that on your @@ -289,7 +289,7 @@ Try calling `s.cost()` as a function and observe that it doesn’t work now that >>> ``` -### (b) Properties and Setters +### Exercise 5.7: Properties and Setters Modify the `shares` attribute so that the value is stored in a private attribute and that a pair of property functions are used to ensure @@ -306,7 +306,7 @@ TypeError: expected an integer >>> ``` -### (c) Adding slots +### Exercise 5.8: Adding slots Modify the `Stock` class so that it has a `__slots__` attribute. Then, verify that new attributes can’t be added: @@ -333,3 +333,5 @@ What happens if you try to inspect the underlying dictionary of `s` above? It should be noted that `__slots__` is most commonly used as an optimization on classes that serve as data structures. Using slots will make such programs use far-less memory and run a bit faster. + +[Contents](../Contents) \| [Previous (5.1 Dictionaries Revisited)](01_Dicts_revisited) \| [Next (6 Generators)](../06_Generators/00_Overview) diff --git a/Notes/06_Generators/01_Iteration_protocol.md b/Notes/06_Generators/01_Iteration_protocol.md index c28548c..c6f834d 100644 --- a/Notes/06_Generators/01_Iteration_protocol.md +++ b/Notes/06_Generators/01_Iteration_protocol.md @@ -86,7 +86,7 @@ for s in port: ## Exercises -### (a) Iteration Illustrated +### Exercise 6.1: Iteration Illustrated Create the following list: @@ -137,7 +137,7 @@ the `__next__()` method of an iterator. Try using it on a file: Keep calling `next(f)` until you reach the end of the file. Watch what happens. -### (b) Supporting Iteration +### Exercise 6.2: Supporting Iteration On occasion, you might want to make one of your own objects support iteration--especially if your object wraps around an existing @@ -249,7 +249,7 @@ Test it to make sure it works: >>> ``` -### (d) Making a more proper container +### Exercise 6.3: Making a more proper container If making a container class, you often want to do more than just iteration. Modify the `Portfolio` class so that it has some other @@ -310,4 +310,4 @@ Python normally work. For container objects, supporting iteration, indexing, containment, and other kinds of operators is an important part of this. -[Next](02_Customizing_iteration) \ No newline at end of file +[Contents](../Contents) \| [Previous (5.2 Encapsulation)](../05_Classes_objects/02_Classes_encapsulation) \| [Next (6.2 Customizing Iteration)](02_Customizing_iteration) diff --git a/Notes/06_Generators/02_Customizing_iteration.md b/Notes/06_Generators/02_Customizing_iteration.md index d351921..275f592 100644 --- a/Notes/06_Generators/02_Customizing_iteration.md +++ b/Notes/06_Generators/02_Customizing_iteration.md @@ -99,7 +99,7 @@ File "", line 1, in ? StopIteration ## Exercises -### (a) A Simple Generator +### Exercise 6.4: A Simple Generator If you ever find yourself wanting to customize iteration, you should always think generator functions. They're easy to write---make @@ -139,7 +139,7 @@ This is kind of interesting--the idea that you can hide a bunch of custom processing in a function and use it to feed a for-loop. The next example looks at a more unusual case. -### (b) Monitoring a streaming data source +### Exercise 6.5: Monitoring a streaming data source Generators can be an interesting way to monitor real-time data sources such as log files or stock market feeds. In this part, we'll @@ -197,7 +197,7 @@ this case, we are using it to repeatedly probe the end of the file to see if more data has been added (`readline()` will either return new data or an empty string). -### (c) Using a generator to produce data +### Exercise 6.6: Using a generator to produce data If you look at the code in part (b), the first part of the code is producing lines of data whereas the statements at the end of the `while` loop are consuming @@ -229,7 +229,7 @@ if __name__ == '__main__': print(f'{name:>10s} {price:>10.2f} {change:>10.2f}') ``` -### (d) Watching your portfolio +### Exercise 6.7: Watching your portfolio Modify the `follow.py` program so that it watches the stream of stock data and prints a ticker showing information for only those stocks @@ -262,4 +262,4 @@ is now this completely general purpose utility that you can use in any program. example, you could use it to watch server logs, debugging logs, and other similar data sources. That's kind of cool. -[Next](03_Producers_consumers) \ No newline at end of file +[Contents](../Contents) \| [Previous (6.1 Iteration Protocol)](01_Iteration_protocol) \| [Next (6.3 Producer/Consumer)](03_Producers_consumers) diff --git a/Notes/06_Generators/03_Producers_consumers.md b/Notes/06_Generators/03_Producers_consumers.md index 556d390..c3f19f3 100644 --- a/Notes/06_Generators/03_Producers_consumers.md +++ b/Notes/06_Generators/03_Producers_consumers.md @@ -101,7 +101,7 @@ You will notice that data incrementally flows through the different functions. For this exercise the `stocksim.py` program should still be running in the background. You’re going to use the `follow()` function you wrote in the previous exercise. -### (a) Setting up a simple pipeline +### Exercise 6.8: Setting up a simple pipeline Let's see the pipelining idea in action. Write the following function: @@ -132,7 +132,7 @@ to it as an argument. Now, try this: It might take awhile for output to appear, but eventually you should see some lines containing data for IBM. -### (b) Setting up a more complex pipeline +### Exercise 6.9: Setting up a more complex pipeline Take the pipelining idea a few steps further by performing more actions. @@ -156,7 +156,7 @@ Well, that's interesting. What you're seeing here is that the output of the `follow()` function has been piped into the `csv.reader()` function and we're now getting a sequence of split rows. -### (c) Making more pipeline components +### Exercise 6.10: Making more pipeline components Let's extend the whole idea into a larger pipeline. In a separate file `ticker.py`, start by creating a function that reads a CSV file as you did above: @@ -237,7 +237,7 @@ Run your program again. You should now a stream of dictionaries like this: ... ``` -### (d) Filtering data +### Exercise 6.11: Filtering data Write a function that filters data. For example: @@ -262,7 +262,7 @@ for row in rows: print(row) ``` -### (e) Putting it all together +### Exercise 6.12: Putting it all together In the `ticker.py` program, write a function `ticker(portfile, logfile, fmt)` that creates a real-time stock ticker from a given portfolio, logfile, @@ -296,6 +296,6 @@ pipelines. In addition, you can create functions that package a series of pipeline stages into a single function call (for example, the `parse_stock_data()` function). -[Next](04_More_generators) +[Contents](../Contents) \| [Previous (6.2 Customizing Iteration)](02_Customizing_iteration) \| [Next (6.4 Generator Expressions)](04_More_generators) diff --git a/Notes/06_Generators/04_More_generators.md b/Notes/06_Generators/04_More_generators.md index 0d701f5..33a5126 100644 --- a/Notes/06_Generators/04_More_generators.md +++ b/Notes/06_Generators/04_More_generators.md @@ -104,7 +104,7 @@ More information at [Generator Tricks for Systems Programmers](http://www.dabeaz In the previous exercises, you wrote some code that followed lines being written to a log file and parsed them into a sequence of rows. This exercise continues to build upon that. Make sure the `Data/stocksim.py` is still running. -### (a) Generator Expressions +### Exercise 6.13: Generator Expressions Generator expressions are a generator version of a list comprehension. For example: @@ -134,7 +134,7 @@ Thus, if you try another for-loop, you get nothing: >>> ``` -### (b) Generator Expressions in Function Arguments +### Exercise 6.14: Generator Expressions in Function Arguments Generator expressions are sometimes placed into function arguments. It looks a little weird at first, but try this experiment: @@ -154,7 +154,7 @@ In your `portfolio.py` file, you performed a few calculations involving list comprehensions. Try replacing these with generator expressions. -### (c) Code simplification +### Exercise 6.15: Code simplification Generators expressions are often a useful replacement for small generator functions. For example, instead of writing a @@ -177,3 +177,4 @@ Modify the `ticker.py` program to use generator expressions as appropriate. +[Contents](../Contents) \| [Previous (6.3 Producer/Consumer)](03_Producers_consumers) \| [Next (7 Advanced Topics)](../07_Advanced_Topics/00_Overview) \ No newline at end of file