From d584afba650c1dad208c164d8f6c0c0bed5d7a55 Mon Sep 17 00:00:00 2001 From: robotuw Date: Sun, 29 Jan 2023 13:20:28 -0700 Subject: [PATCH 01/90] Update intro-TheWayoftheProgram.ptx Test change to see what happens. The first section of the first chapter should be slightly updated. --- pretext/GeneralIntro/intro-TheWayoftheProgram.ptx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx index 84fafc779..8d320b2c4 100644 --- a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx +++ b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx @@ -1,7 +1,7 @@
The Way of the Program -

The goal of this book is to teach you to think like a computer scientist. This +

The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they From 0b41e314e875c1b2374864830cd5e1be8cb158ce Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sun, 29 Jan 2023 14:33:22 -0700 Subject: [PATCH 02/90] Update intro-TheWayoftheProgram.ptx --- pretext/GeneralIntro/intro-TheWayoftheProgram.ptx | 1 + 1 file changed, 1 insertion(+) diff --git a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx index 8d320b2c4..86e611d5b 100644 --- a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx +++ b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx @@ -1,6 +1,7 @@

The Way of the Program +

Testing

The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal From e645ff0e743789a2d19b9c2a296a924afeea07a9 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sun, 29 Jan 2023 14:47:14 -0700 Subject: [PATCH 03/90] Update intro-TheWayoftheProgram.ptx --- pretext/GeneralIntro/intro-TheWayoftheProgram.ptx | 1 - 1 file changed, 1 deletion(-) diff --git a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx index 86e611d5b..8d320b2c4 100644 --- a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx +++ b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx @@ -1,7 +1,6 @@

The Way of the Program -

Testing

The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal From 8651f0dcf643e79fbafecff22384b03e6ef646b7 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sun, 29 Jan 2023 16:36:44 -0700 Subject: [PATCH 04/90] Update intro-TheWayoftheProgram.rst --- _sources/GeneralIntro/intro-TheWayoftheProgram.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 305ec46cb..45e1e6806 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,7 +10,7 @@ The Way of the Program ====================== -The goal of this book is to teach you to think like a computer scientist. This +The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they From bb11f51b7b850628090e0ef17a3f41fc93bfef3d Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:01:42 -0700 Subject: [PATCH 05/90] Update intro-TheWayoftheProgram.rst --- _sources/GeneralIntro/intro-TheWayoftheProgram.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 45e1e6806..00f2c8923 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,6 +10,8 @@ The Way of the Program ====================== +Test Section + The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal From 2c5ff70b284baf8ea756b7ea97b117c2d9548b56 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Tue, 31 Jan 2023 08:40:34 -0700 Subject: [PATCH 06/90] Webhook test --- _sources/GeneralIntro/intro-TheWayoftheProgram.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 00f2c8923..45e1e6806 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,8 +10,6 @@ The Way of the Program ====================== -Test Section - The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal From b5cad79da5f264529d9b1ee13689bdf844e57e54 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Wed, 1 Feb 2023 21:07:25 -0700 Subject: [PATCH 07/90] Update intro-TheWayoftheProgram.rst --- _sources/GeneralIntro/intro-TheWayoftheProgram.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 45e1e6806..305ec46cb 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,7 +10,7 @@ The Way of the Program ====================== -The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This +The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they From ef8f9f6218aadd3f8669caa2b2c9f70cd8c157be Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 2 Feb 2023 17:11:48 -0700 Subject: [PATCH 08/90] Webhook check Can I see the changes deployed on the server without another human having to be involved? --- _sources/GeneralIntro/intro-TheWayoftheProgram.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 305ec46cb..2f92901e3 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,7 +10,7 @@ The Way of the Program ====================== -The goal of this book is to teach you to think like a computer scientist. This +Blah, blah blah. The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they From 8d5dda6744110218753174b4473b25ea9dbf90d3 Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 9 Feb 2023 16:47:24 -0700 Subject: [PATCH 09/90] Chapter Reordering Attempt 1 Figure out how to shuffle chapters. Attempt #1 is via index.rst --- _sources/index.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/_sources/index.rst b/_sources/index.rst index 05921b03d..81e34244e 100644 --- a/_sources/index.rst +++ b/_sources/index.rst @@ -55,23 +55,23 @@ Table of Contents GeneralIntro/toctree.rst SimplePythonData/toctree.rst Debugging/toctree.rst + Strings/toctree.rst + Lists/toctree.rst + Selection/toctree.rst + MoreAboutIteration/toctree.rst PythonTurtle/toctree.rst PythonModules/toctree.rst Functions/toctree.rst - Selection/toctree.rst - MoreAboutIteration/toctree.rst - Strings/toctree.rst - Lists/toctree.rst Files/toctree.rst - Dictionaries/toctree.rst Exceptions/toctree.rst - WebApps/toctree.rst - GUIandEventDrivenProgramming/toctree.rst IntroRecursion/toctree.rst ClassesBasics/toctree.rst ClassesDiggingDeeper/toctree.rst Inheritance/toctree.rst UnitTesting/toctree.rst + Dictionaries/toctree.rst + WebApps/toctree.rst + GUIandEventDrivenProgramming/toctree.rst Labs :::: From 12778a6f8fae8f8b19f075981c075efab38426c4 Mon Sep 17 00:00:00 2001 From: robotuw Date: Sat, 11 Feb 2023 14:07:50 -0700 Subject: [PATCH 10/90] Week1-4 Update Lots of shuffling around, some content updates. Content setting for weeks 1 through 4. --- .../GeneralIntro/intro-TheWayoftheProgram.rst | 2 +- _sources/Lists/Aliasing.rst | 2 +- _sources/Lists/AppendversusConcatenate.rst | 2 +- _sources/Lists/CloningLists.rst | 2 +- _sources/Lists/ConcatenationandRepetition.rst | 2 +- _sources/Lists/ListDeletion.rst | 2 +- _sources/Lists/ListMembership.rst | 2 +- _sources/Lists/ListMethods.rst | 2 +- _sources/Lists/ListSlices.rst | 2 +- _sources/Lists/Listsandforloops.rst | 2 +- _sources/Lists/ListsareMutable.rst | 2 +- _sources/Lists/ObjectsandReferences.rst | 2 +- _sources/Lists/RepetitionandReferences.rst | 2 +- _sources/Lists/StringsandLists.rst | 2 +- .../Lists/TheAccumulatorPatternwithLists.rst | 2 +- _sources/Lists/TheReturnofLSystems.rst | 2 +- _sources/Lists/UsingListsasParameters.rst | 2 +- _sources/Lists/toctree.rst | 8 +- _sources/Selection/Chainedconditionals.rst | 22 ------ _sources/Selection/toctree.rst | 4 +- _sources/Strings/ACollectionDataType.rst | 11 ++- _sources/Strings/StringComparison.rst | 2 +- _sources/Strings/StringMethods.rst | 73 ++++++------------- _sources/Strings/StringsareImmutable.rst | 2 +- _sources/Strings/TheSliceOperator.rst | 3 - _sources/Strings/toctree.rst | 2 +- _sources/index.rst | 2 +- 27 files changed, 55 insertions(+), 108 deletions(-) diff --git a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst index 2f92901e3..305ec46cb 100644 --- a/_sources/GeneralIntro/intro-TheWayoftheProgram.rst +++ b/_sources/GeneralIntro/intro-TheWayoftheProgram.rst @@ -10,7 +10,7 @@ The Way of the Program ====================== -Blah, blah blah. The goal of this book is to teach you to think like a computer scientist. This +The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they diff --git a/_sources/Lists/Aliasing.rst b/_sources/Lists/Aliasing.rst index 8525b989d..560b4d9c5 100644 --- a/_sources/Lists/Aliasing.rst +++ b/_sources/Lists/Aliasing.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-11- + :prefix: list-14- :start: 1 .. index:: alias diff --git a/_sources/Lists/AppendversusConcatenate.rst b/_sources/Lists/AppendversusConcatenate.rst index 83d67bb3f..a169ff6c8 100644 --- a/_sources/Lists/AppendversusConcatenate.rst +++ b/_sources/Lists/AppendversusConcatenate.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-16- + :prefix: list-11- :start: 1 Append versus Concatenate diff --git a/_sources/Lists/CloningLists.rst b/_sources/Lists/CloningLists.rst index 3376aa8b1..9c7677363 100644 --- a/_sources/Lists/CloningLists.rst +++ b/_sources/Lists/CloningLists.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-12- + :prefix: list-15- :start: 1 .. index:: clone diff --git a/_sources/Lists/ConcatenationandRepetition.rst b/_sources/Lists/ConcatenationandRepetition.rst index 6114d799d..74aa97796 100644 --- a/_sources/Lists/ConcatenationandRepetition.rst +++ b/_sources/Lists/ConcatenationandRepetition.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-6- + :prefix: list-5- :start: 1 .. index:: diff --git a/_sources/Lists/ListDeletion.rst b/_sources/Lists/ListDeletion.rst index e5dd5a6e5..0d6d3638a 100644 --- a/_sources/Lists/ListDeletion.rst +++ b/_sources/Lists/ListDeletion.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-9- + :prefix: list-8- :start: 1 .. index:: del; a list portion diff --git a/_sources/Lists/ListMembership.rst b/_sources/Lists/ListMembership.rst index b77dfe2b7..a47245a1c 100644 --- a/_sources/Lists/ListMembership.rst +++ b/_sources/Lists/ListMembership.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-5- + :prefix: list-12- :start: 1 .. index:: in; membership operator diff --git a/_sources/Lists/ListMethods.rst b/_sources/Lists/ListMethods.rst index 21e44e220..509025559 100644 --- a/_sources/Lists/ListMethods.rst +++ b/_sources/Lists/ListMethods.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-14- + :prefix: list-9- :start: 1 List Methods diff --git a/_sources/Lists/ListSlices.rst b/_sources/Lists/ListSlices.rst index edfe3147b..ec90110e5 100644 --- a/_sources/Lists/ListSlices.rst +++ b/_sources/Lists/ListSlices.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-7- + :prefix: list-6- :start: 1 .. index:: diff --git a/_sources/Lists/Listsandforloops.rst b/_sources/Lists/Listsandforloops.rst index 9d7a87e58..36bd171fb 100644 --- a/_sources/Lists/Listsandforloops.rst +++ b/_sources/Lists/Listsandforloops.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-17- + :prefix: list-18- :start: 1 Lists and ``for`` loops diff --git a/_sources/Lists/ListsareMutable.rst b/_sources/Lists/ListsareMutable.rst index ef901545e..cfc3c6c30 100644 --- a/_sources/Lists/ListsareMutable.rst +++ b/_sources/Lists/ListsareMutable.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-8- + :prefix: list-7- :start: 1 Lists are Mutable diff --git a/_sources/Lists/ObjectsandReferences.rst b/_sources/Lists/ObjectsandReferences.rst index c39a2db5a..2efdfbf84 100644 --- a/_sources/Lists/ObjectsandReferences.rst +++ b/_sources/Lists/ObjectsandReferences.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-10- + :prefix: list-13- :start: 1 diff --git a/_sources/Lists/RepetitionandReferences.rst b/_sources/Lists/RepetitionandReferences.rst index b353e0e18..ee8b4f302 100644 --- a/_sources/Lists/RepetitionandReferences.rst +++ b/_sources/Lists/RepetitionandReferences.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-13- + :prefix: list-16- :start: 1 Repetition and References diff --git a/_sources/Lists/StringsandLists.rst b/_sources/Lists/StringsandLists.rst index f2de1e085..b1c4fd3f2 100644 --- a/_sources/Lists/StringsandLists.rst +++ b/_sources/Lists/StringsandLists.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-24- + :prefix: list-10- :start: 1 Strings and Lists diff --git a/_sources/Lists/TheAccumulatorPatternwithLists.rst b/_sources/Lists/TheAccumulatorPatternwithLists.rst index 5e77a5b1a..a1f3cddf5 100644 --- a/_sources/Lists/TheAccumulatorPatternwithLists.rst +++ b/_sources/Lists/TheAccumulatorPatternwithLists.rst @@ -7,7 +7,7 @@ License". .. qnum:: - :prefix: list-29- + :prefix: list-19- :start: 1 .. _accumulator_lists: diff --git a/_sources/Lists/TheReturnofLSystems.rst b/_sources/Lists/TheReturnofLSystems.rst index 3bfb82339..c91622fc1 100644 --- a/_sources/Lists/TheReturnofLSystems.rst +++ b/_sources/Lists/TheReturnofLSystems.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-15- + :prefix: list-17- :start: 1 The Return of L-Systems diff --git a/_sources/Lists/UsingListsasParameters.rst b/_sources/Lists/UsingListsasParameters.rst index 8f6cbc43a..09398e42e 100644 --- a/_sources/Lists/UsingListsasParameters.rst +++ b/_sources/Lists/UsingListsasParameters.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: list-18- + :prefix: list-20- :start: 1 Using Lists as Parameters diff --git a/_sources/Lists/toctree.rst b/_sources/Lists/toctree.rst index 3b79795c2..ffd1c81fa 100644 --- a/_sources/Lists/toctree.rst +++ b/_sources/Lists/toctree.rst @@ -9,18 +9,19 @@ Lists ListValues.rst ListLength.rst AccessingElements.rst - ListMembership.rst ConcatenationandRepetition.rst ListSlices.rst ListsareMutable.rst ListDeletion.rst + ListMethods.rst + StringsandLists.rst + AppendversusConcatenate.rst + ListMembership.rst ObjectsandReferences.rst Aliasing.rst CloningLists.rst RepetitionandReferences.rst - ListMethods.rst TheReturnofLSystems.rst - AppendversusConcatenate.rst Listsandforloops.rst TheAccumulatorPatternwithLists.rst UsingListsasParameters.rst @@ -29,7 +30,6 @@ Lists FunctionsthatProduceLists.rst ListComprehensions.rst NestedLists.rst - StringsandLists.rst listTypeConversionFunction.rst TuplesandMutability.rst TupleAssignment.rst diff --git a/_sources/Selection/Chainedconditionals.rst b/_sources/Selection/Chainedconditionals.rst index ec543f191..96b3a669b 100644 --- a/_sources/Selection/Chainedconditionals.rst +++ b/_sources/Selection/Chainedconditionals.rst @@ -135,26 +135,4 @@ Here is the same program using ``elif``. print(x, " is 0") -.. mchoice:: test_question6_7_2 - :practice: T - :answer_a: a - :answer_b: b - :answer_c: c - :correct: c - :feedback_a: While the value in x is less than the value in y (3 is less than 5) it is not less than the value in z (3 is not less than 2). - :feedback_b: The value in y is not less than the value in x (5 is not less than 3). - :feedback_c: Since the first two Boolean expressions are false the else will be executed. - - What will the following code print if x = 3, y = 5, and z = 2? - - .. code-block:: python - - if x < y and x < z: - print("a") - elif y < x and y < z: - print("b") - else: - print("c") - - diff --git a/_sources/Selection/toctree.rst b/_sources/Selection/toctree.rst index cd2eb1482..03604c8e8 100644 --- a/_sources/Selection/toctree.rst +++ b/_sources/Selection/toctree.rst @@ -6,12 +6,12 @@ Selection :maxdepth: 2 BooleanValuesandBooleanExpressions.rst - Logicaloperators.rst - PrecedenceofOperators.rst ConditionalExecutionBinarySelection.rst OmittingtheelseClauseUnarySelection.rst Nestedconditionals.rst Chainedconditionals.rst + Logicaloperators.rst + PrecedenceofOperators.rst BooleanFunctions.rst Glossary.rst Exercises.rst diff --git a/_sources/Strings/ACollectionDataType.rst b/_sources/Strings/ACollectionDataType.rst index 03c5e92c7..e8eda97bf 100644 --- a/_sources/Strings/ACollectionDataType.rst +++ b/_sources/Strings/ACollectionDataType.rst @@ -14,12 +14,10 @@ A Collection Data Type ---------------------- -So far we have seen built-in types like: ``int``, ``float``, -``bool``, ``str`` and we've seen lists. -``int``, ``float``, and -``bool`` are considered to be simple or primitive data types because their values are not composed +So far we have seen built-in types like: ``int``, ``float``, and ``str``. +``int`` and ``float`` are considered to be simple or primitive data types because their values are not composed of any smaller parts. They cannot be broken down. -On the other hand, strings and lists are different from the others because they +On the other hand, strings (and lists that we will talk about next chapter) are different from the others because they are made up of smaller pieces. In the case of strings, they are made up of smaller strings each containing one **character**. @@ -30,7 +28,8 @@ single entity (the whole), or we may want to access its parts. This ambiguity is Strings can be defined as sequential collections of characters. This means that the individual characters that make up the string are assumed to be in a particular order from left to right. -A string that contains no characters, often referred to as the **empty string**, is still considered to be a string. It is simply a sequence of zero characters and is represented by '' or "" (two single or two double quotes with nothing in between). +A string that contains no characters, often referred to as the **empty string**, is still considered to be a string. +It is simply a sequence of zero characters and is represented by '' or "" (two single or two double quotes with nothing in between). .. index:: string operations, concatenation diff --git a/_sources/Strings/StringComparison.rst b/_sources/Strings/StringComparison.rst index e239e4b69..e566331e4 100644 --- a/_sources/Strings/StringComparison.rst +++ b/_sources/Strings/StringComparison.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: strings-8- + :prefix: strings-9- :start: 1 diff --git a/_sources/Strings/StringMethods.rst b/_sources/Strings/StringMethods.rst index 307cfda0a..c08c30fe6 100644 --- a/_sources/Strings/StringMethods.rst +++ b/_sources/Strings/StringMethods.rst @@ -16,13 +16,11 @@ String Methods -------------- -We previously saw that each turtle instance has its own attributes and -a number of methods that can be applied to the instance. For example, -we wrote ``tess.right(90)`` when we wanted the turtle object ``tess`` to perform the ``right`` method to turn -to the right 90 degrees. The "dot notation" is the way we connect the name of an object to the name of a method -it can perform. +We previously used a few functions like ``print()`` and ``input()``. A **method** is a function that is attached to a specific Python object. +To access this function, we write the object, then a dot ``.``, and then the name of the method. The "dot notation" is the way we connect the name of an object to the name of a method +it can perform. For example, we can write ``ss.upper()`` when we wanted the string ``ss`` to perform the ``upper()`` method to create an upper-case version of itself. -Strings are also objects. Each string instance has its own attributes and methods. The most important attribute of the string is the collection of characters. There are a wide variety of methods. Try the following program. +Remember that Strings are objects. Each string instance has its own attributes and methods. The most important attribute of the string is the collection of characters. There are a wide variety of methods. Try the following program. .. activecode:: chp08_upper @@ -157,7 +155,7 @@ change the original. You can also consult the `Python documentation for strings .. _Format-Strings: -String Format Method +F-Strings ~~~~~~~~~~~~~~~~~~~~~ In grade school quizzes a common convention is to use fill-in-the blanks. For instance, @@ -168,26 +166,25 @@ In grade school quizzes a common convention is to use fill-in-the blanks. For in and you can fill in the name of the person greeted, and combine given text with a chosen insertion. *We use this as an analogy:* Python has a similar -construction, better called fill-in-the-braces. The string method ``format``, makes +construction, called a formatted string or an **f-string**. An f-string makes substitutions into places in a string enclosed in braces. Run this code: .. activecode:: ch08_methods3 person = input('Your name: ') - greeting = 'Hello {}!'.format(person) + greeting = f'Hello {person}!' print(greeting) There are several new ideas here! -The string for the ``format`` method has a special form, with braces embedded. -Such a string is called a *format string*. Places where -braces are embedded are replaced by the value of an expression -taken from the parameter list for the ``format`` method. There are many +The string has been formatted in a new way. We have included an ``f`` before the starting quotation mark. +Such a string is called an *f-string*. Places where +braces are embedded are replaced by the value of the expression inside the braces. There are many variations on the syntax between the braces. In this case we use the syntax where the first (and only) location in the string with -braces has a substitution made from the first (and only) parameter. +braces has the variable ``person``. When this code is evaluated, the value of the person variable is placed in the string in this location. In the code above, this new string is assigned to the identifier ``greeting``, and then the string is printed. @@ -201,7 +198,7 @@ version: .. activecode:: ch08_methods4 person = input('Enter your name: ') - print('Hello {}!'.format(person)) + print(f'Hello {person}!') There can be multiple substitutions, with data of any type. Next we use floats. Try original price $2.50 with a 7% discount: @@ -211,35 +208,29 @@ Next we use floats. Try original price $2.50 with a 7% discount: origPrice = float(input('Enter the original price: $')) discount = float(input('Enter discount percentage: ')) newPrice = (1 - discount/100)*origPrice - calculation = '${} discounted by {}% is ${}.'.format(origPrice, discount, newPrice) + calculation = f'${origPrice} discounted by {discount}% is ${newPrice}.' print(calculation) -The parameters are inserted into the braces in order. - If you used the data suggested, this result is not satisfying. Prices should appear with exactly two places beyond the decimal point, but that is not the default way to display floats. -Format strings can give further information inside the braces +F-strings can give further information inside the braces showing how to specially format data. In particular floats can be shown with a specific number of decimal places. -For two decimal places, put ``:.2f`` inside the braces for the monetary values: +For two decimal places, put ``:.2f`` inside the braces but after the variable name for the monetary values: .. activecode:: ch08_methods6 origPrice = float(input('Enter the original price: $')) discount = float(input('Enter discount percentage: ')) newPrice = (1 - discount/100)*origPrice - calculation = '${:.2f} discounted by {}% is ${:.2f}.'.format(origPrice, discount, newPrice) + calculation = f'${origPrice:.2f} discounted by {discount}% is ${newPrice:.2f}.' print(calculation) The 2 in the format modifier can be replaced by another integer to round to that specified number of digits. -This kind of format string depends directly on the order of the -parameters to the format method. There are other approaches that we will -skip here, explicitly numbering substitutions and taking substitutions from a dictionary. - A technical point: Since braces have special meaning in a format string, there must be a special rule if you want braces to actually be included in the final *formatted* string. The rule is to double @@ -251,40 +242,22 @@ formatted string:: a = 5 b = 9 - setStr = 'The set is {​{ {},{} }​}.'.format(a, b) + setStr = f'The set is {​{ {a},{b} }​}.' print(setStr) Unfortunately, at the time of this writing, the ActiveCode format implementation has a bug, printing doubled braces, but standard Python prints ``{5, 9}``. -You can have multiple placeholders indexing the same argument, or perhaps even have extra -arguments that are not referenced at all: - -.. activecode:: ch08_formatspecification - - letter = """ - Dear {0} {2}. - {0}, I have an interesting money-making proposition for you! - If you deposit $10 million into my bank account, I can - double your money ... - """ - - print(letter.format("Paris", "Whitney", "Hilton")) - print(letter.format("Bill", "Henry", "Gates")) - - - - .. mchoice:: test_question8_3_3 :practice: T :answer_a: Nothing - it causes an error - :answer_b: sum of {} and {} is {}; product: {}. 2 6 8 12 + :answer_b: sum of {} and {} is {}; product: {}. :answer_c: sum of 2 and 6 is 8; product: 12. :answer_d: sum of {2} and {6} is {8}; product: {12}. :correct: c - :feedback_a: It is legal format syntax: put the data in place of the braces. - :feedback_b: Put the data into the format string; not after it. - :feedback_c: Yes, correct substitutions! + :feedback_a: It is legal format syntax. + :feedback_b: Put the value of each expression in place of the braces. + :feedback_c: Yes, correct! :feedback_d: Close: REPLACE the braces. @@ -294,7 +267,7 @@ arguments that are not referenced at all: x = 2 y = 6 - print('sum of {} and {} is {}; product: {}.'.format( x, y, x+y, x*y)) + print(f'sum of {x} and {y} is {x+y}; product: {x*y}.') .. mchoice:: test_question8_3_4 @@ -313,6 +286,6 @@ arguments that are not referenced at all: .. code-block:: python v = 2.34567 - print('{:.1f} {:.2f} {:.7f}'.format(v, v, v)) + print(f'{v:.1f} {v:.2f} {v:.7f}') diff --git a/_sources/Strings/StringsareImmutable.rst b/_sources/Strings/StringsareImmutable.rst index 3e4bca44e..ad934011e 100644 --- a/_sources/Strings/StringsareImmutable.rst +++ b/_sources/Strings/StringsareImmutable.rst @@ -8,7 +8,7 @@ License". .. qnum:: - :prefix: strings-9- + :prefix: strings-8- :start: 1 .. index:: mutable, immutable diff --git a/_sources/Strings/TheSliceOperator.rst b/_sources/Strings/TheSliceOperator.rst index f8fb8082d..283f00dc3 100644 --- a/_sources/Strings/TheSliceOperator.rst +++ b/_sources/Strings/TheSliceOperator.rst @@ -32,9 +32,6 @@ selecting a character: The `slice` operator ``[n:m]`` returns the part of the string from the n'th character to the m'th character, including the first but excluding the last. In other words, start with the character at index n and go up to but do not include the character at index m. -This -behavior may seem counter-intuitive but if you recall the ``range`` function, it did not include its end -point either. If you omit the first index (before the colon), the slice starts at the beginning of the string. If you omit the second index, the slice goes to the diff --git a/_sources/Strings/toctree.rst b/_sources/Strings/toctree.rst index 86ae0ba68..8614a42a8 100644 --- a/_sources/Strings/toctree.rst +++ b/_sources/Strings/toctree.rst @@ -12,8 +12,8 @@ Strings StringMethods.rst Length.rst TheSliceOperator.rst - StringComparison.rst StringsareImmutable.rst + StringComparison.rst TraversalandtheforLoopByItem.rst TraversalandtheforLoopByIndex.rst TraversalandthewhileLoop.rst diff --git a/_sources/index.rst b/_sources/index.rst index 81e34244e..0ea5c8280 100644 --- a/_sources/index.rst +++ b/_sources/index.rst @@ -54,10 +54,10 @@ Table of Contents GeneralIntro/toctree.rst SimplePythonData/toctree.rst - Debugging/toctree.rst Strings/toctree.rst Lists/toctree.rst Selection/toctree.rst + Debugging/toctree.rst MoreAboutIteration/toctree.rst PythonTurtle/toctree.rst PythonModules/toctree.rst From 103da7beb4f04cf5803e5e6045852e126f96abe4 Mon Sep 17 00:00:00 2001 From: robotuw Date: Sun, 12 Feb 2023 10:41:53 -0700 Subject: [PATCH 11/90] Loops chapter revised This was a complex one. Pushing now to see how changes went. --- .../FlowofExecutionofthewhileLoop.rst | 52 +++++ .../SentinelValuesAndValidation.rst | 56 +++-- .../MoreAboutIteration/The3n1Sequence.rst | 29 +-- _sources/MoreAboutIteration/TheforLoop.rst | 87 ++++++++ .../MoreAboutIteration/TherangeFunction.rst | 193 ++++++++++++++++++ .../MoreAboutIteration/ThewhileStatement.rst | 166 +++++++-------- .../intro-IterationRevisited.rst | 8 +- _sources/MoreAboutIteration/toctree.rst | 15 +- .../ConditionalExecutionBinarySelection.rst | 18 +- 9 files changed, 463 insertions(+), 161 deletions(-) create mode 100644 _sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst create mode 100644 _sources/MoreAboutIteration/TheforLoop.rst create mode 100644 _sources/MoreAboutIteration/TherangeFunction.rst diff --git a/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst new file mode 100644 index 000000000..1f8e38d99 --- /dev/null +++ b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst @@ -0,0 +1,52 @@ +.. Copyright (C) Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris + Meyers, and Dario Mitchell. Permission is granted to copy, distribute + and/or modify this document under the terms of the GNU Free Documentation + License, Version 1.3 or any later version published by the Free Software + Foundation; with Invariant Sections being Forward, Prefaces, and + Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of + the license is included in the section entitled "GNU Free Documentation + License". + +.. qnum:: + :prefix: turtle-5- + :start: 1 + +.. index:: control flow, flow of execution + + + +Flow of Execution of the while Loop +--------------------------------- + +As a program executes, the interpreter always keeps track of which statement is +about to be executed. We call this the **control flow**, or the **flow of +execution** of the program. When humans execute programs, they often use their +finger to point to each statement in turn. So you could think of control flow +as "Python's moving finger". + +Control flow until now has been strictly top to bottom, one statement at a +time. We call this type of control **sequential**. In Python flow is sequential as long as +successive statements are indented the *same* amount. The ``while`` statement +introduces indented sub-statements after the while-loop heading. + +Flow of control is often easy to visualize and understand if we draw a flowchart. +This flowchart shows the exact steps and logic of how the ``while`` statement executes. + +.. image:: Figures/while_flow.png + :width: 300px + :align: center + + +A codelens demonstration is a good way to help you visualize exactly how the flow of control +works with the while loop. Try stepping forward and backward through the program by pressing +the buttons. You can see the value of ``count`` change as the loop iterates through the values from 10 to 0. + +.. codelens:: vtest + + count = 10 + while count > 0: + print(count) + count = count - 1 + print("Blastoff!") + + diff --git a/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst b/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst index a5f14f344..67badd49b 100644 --- a/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst +++ b/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst @@ -21,7 +21,7 @@ Other uses of ``while`` Sentinel Values ~~~~~~~~~~~~~~~~~~~ -Indefinite loops are much more common in the real world than definite loops. +The indefinite loops provided by the ``while`` statement are common in the real world. * If you are selling tickets to an event, you don't know in advance how many tickets you will sell. You keep selling tickets as long as people come @@ -61,24 +61,21 @@ zero is a **sentinel value**, a value used to signal the end of the loop. Here's .. activecode:: ch07_sentinel :timelimit: 60000 - def checkout(): - total = 0 - count = 0 - moreItems = True - while moreItems: - price = float(input('Enter price of item (0 when done): ')) - if price != 0: - count = count + 1 - total = total + price - print('Subtotal: $', total) - else: - moreItems = False - average = total / count - print('Total items:', count) - print('Total $', total) - print('Average price per item: $', average) - - checkout() + total = 0 + count = 0 + moreItems = True + while moreItems: + price = float(input('Enter price of item (0 when done): ')) + if price != 0: + count = count + 1 + total = total + price + print('Subtotal: $', total) + else: + moreItems = False + average = total / count + print('Total items:', count) + print('Total $', total) + print('Average price per item: $', average) There are still a few problems with this program. @@ -123,18 +120,15 @@ When you run the following code, try typing something other than Y or N to see h .. activecode:: ch07_validation :timelimit: 60000 - def get_yes_or_no(message): - valid_input = False - answer = input(message) - while not valid_input: - answer = answer.upper() # convert to upper case - if answer == 'Y' or answer == 'N': - valid_input = True - else: - answer = input('Please enter Y for yes or N for no. \n' + message) - return answer - - response = get_yes_or_no('Do you like lima beans? Y)es or N)o: ') + valid_input = False + response = input('Do you like lima beans? Y)es or N)o: ') + while not valid_input: + response = response.upper() # convert to upper case + if response == 'Y' or response == 'N': + valid_input = True + else: + response = input('Please enter Y for yes or N for no. \n' + message) + if response == 'Y': print('Great! They are very healthy.') else: diff --git a/_sources/MoreAboutIteration/The3n1Sequence.rst b/_sources/MoreAboutIteration/The3n1Sequence.rst index 25d0b377d..983638731 100644 --- a/_sources/MoreAboutIteration/The3n1Sequence.rst +++ b/_sources/MoreAboutIteration/The3n1Sequence.rst @@ -21,21 +21,20 @@ the next term of the sequence from ``n``, either by halving ``n``, whenever ``n`` is even, or else by multiplying it by three and adding 1 when it is odd. The sequence terminates when ``n`` reaches 1. -This Python function captures that algorithm. Try running this program several times supplying different values for n. +This Python code captures that algorithm. Try running this program several times supplying different values for n. .. activecode:: ch07_indef1 - def seq3np1(n): - """ Print the 3n+1 sequence from n, terminating when it reaches 1.""" - while n != 1: - print(n) - if n % 2 == 0: # n is even - n = n // 2 - else: # n is odd - n = n * 3 + 1 - print(n) # the last print is 1 - - seq3np1(3) + n = 3 + + """ Print the 3n+1 sequence from n, terminating when it reaches 1.""" + while n != 1: + print(n) + if n % 2 == 0: # n is even + n = n // 2 + else: # n is odd + n = n * 3 + 1 + print(n) # the last print is 1 @@ -57,12 +56,6 @@ time through the loop until it reaches 1. You might like to have some fun and see if you can find a small starting number that needs more than a hundred steps before it terminates. - -.. admonition:: Lab - - * `Experimenting with the 3n+1 Sequence <../Labs/sequencelab.html>`_ In this guided lab exercise we will try to learn more about this sequence. - - Particular values aside, the interesting question is whether we can prove that this sequence terminates for *all* positive values of ``n``. So far, no one has been able to prove it *or* disprove it! diff --git a/_sources/MoreAboutIteration/TheforLoop.rst b/_sources/MoreAboutIteration/TheforLoop.rst new file mode 100644 index 000000000..46e28602b --- /dev/null +++ b/_sources/MoreAboutIteration/TheforLoop.rst @@ -0,0 +1,87 @@ +.. Copyright (C) Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris + Meyers, and Dario Mitchell. Permission is granted to copy, distribute + and/or modify this document under the terms of the GNU Free Documentation + License, Version 1.3 or any later version published by the Free Software + Foundation; with Invariant Sections being Forward, Prefaces, and + Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of + the license is included in the section entitled "GNU Free Documentation + License". + +.. qnum:: + :prefix: turtle-3- + :start: 1 + +.. index:: for loop, iteration, body + loop; for + +The ``for`` Loop +---------------- + +.. youtube:: xGSfiZt5cdw + :divid: forloopvid + :height: 315 + :width: 560 + :align: left + +The ``while`` statement is a general-purpose tool for iteration, and is necessary for any instance of iteration where we don't know how many repetitions will be needed. +However, if we do know how many are needed, there is a more efficient method: the ``for`` statement. + +As a simple example, let's say we have some friends, and +we'd like to send them each an email inviting them to our party. We +don't quite know how to send email yet, so for the moment we'll just print a +message for each friend. + +.. activecode:: ch03_4 + :nocanvas: + :tour_1: "Overall Tour"; 1-2: Example04_Tour01_Line01; 2: Example04_Tour01_Line02; 1: Example04_Tour01_Line03; + + for name in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: + print(f"Hi {name}! Please come to my party on Saturday!") + + +Take a look at the output produced when you press the ``run`` button. There is one line printed for each friend. Here's how it works: + + +* **name** in this ``for`` statement is the **loop variable**. +* The list of names in the square brackets is a regular list. Later we'll see that other types besides lists can be put in this spot. +* Line 2 is the **loop body**. Like with while, the loop body is always + indented. The loop body is performed one time for each name in the list. +* On each *iteration* or *pass* of the loop, a check is done to see if + there are still more items to be processed. If there are none left (this is + called the **terminating condition** of the loop), the loop has finished. + Program execution continues at the next statement after the loop body. +* If there are items still to be processed, the loop variable is updated to + refer to the next item in the list. This means, in this case, that the loop + body is executed here 7 times, and each time ``name`` will refer to a different + friend. +* At the end of each execution of the body of the loop, Python returns + to the ``for`` statement, to see if there are more items to be handled. + +.. note:: + + Introduction of the for statement causes us to think about the types of iteration we have seen. The ``for`` statement will always iterate through a sequence of + values like the list of names for the party. + Since we know that it will iterate once for each value in the collection, it is often said that a ``for`` loop creates a + **definite iteration** because we definitely know how many times we are going to iterate. On the other + hand, the ``while`` statement is dependent on a condition that needs to evaluate to ``False`` in order + for the loop to terminate. Since we do not necessarily know when this will happen, it creates what we + call **indefinite iteration**. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition + controlling the iteration will fail and the iteration will stop. (Unless we have an infinite loop which is of course a problem.) + +What you will notice here is that the ``while`` loop is more work for +you --- the programmer --- than the equivalent ``for`` loop. When using a ``while`` +loop you have to control the loop variable yourself. You give it an initial value, test +for completion, and then make sure you change something in the body so that the loop +terminates. + +**Check your understanding** + +.. mchoice:: test_question7_6_1 + :practice: T + :answer_a: True + :answer_b: False + :correct: a + :feedback_a: Although the while loop uses a different syntax, it is just as powerful as a for-loop and often more flexible. + :feedback_b: Often a for-loop is more natural and convenient for a task, but that same task can always be expressed using a while loop. + + True or False: You can rewrite any for-loop as a while-loop. diff --git a/_sources/MoreAboutIteration/TherangeFunction.rst b/_sources/MoreAboutIteration/TherangeFunction.rst new file mode 100644 index 000000000..fcafc68c3 --- /dev/null +++ b/_sources/MoreAboutIteration/TherangeFunction.rst @@ -0,0 +1,193 @@ +.. Copyright (C) Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris + Meyers, and Dario Mitchell. Permission is granted to copy, distribute + and/or modify this document under the terms of the GNU Free Documentation + License, Version 1.3 or any later version published by the Free Software + Foundation; with Invariant Sections being Forward, Prefaces, and + Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of + the license is included in the section entitled "GNU Free Documentation + License". + +.. qnum:: + :prefix: turtle-8- + :start: 1 + +The range Function +------------------ + +.. youtube:: YK8QlIT3__M + :divid: advrange + :height: 315 + :width: 560 + :align: left + +In our first example of a while loop, we counted down from 10 to 0. If we were to consider doing this with a for loop, we would need to construct our own series of numbers +to loop through them. + +It turns out that generating lists with a specific number of integers is a very common thing to do, especially when you +want to write simple ``for loop`` controlled iteration. The conventional thing to do is to use a list of integers starting with 0. +In fact, these lists are so popular that Python gives us special built-in ``range`` objects that can deliver a sequence of values to +the ``for`` loop. When called with one parameter, the sequence provided by ``range`` always starts with 0. If you ask for ``range(4)``, then you will get 4 values starting with 0. In other words, 0, 1, 2, and finally 3. Notice that 4 is not included since we started with 0. Likewise, ``range(10)`` provides 10 values, 0 through 9. + +.. sourcecode:: python + + for i in range(4): + # Executes the body with i = 0, then 1, then 2, then 3 + for x in range(10): + # sets x to each of ... [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +.. note:: + + Computer scientists like to count from 0! + + +So to count something ten times, a good Python programmer would do this: + +.. sourcecode:: python + + for i in range(10): + #do something + + +The `range `_ function is actually a very powerful function +when it comes to +creating sequences of integers. It can take one, two, or three parameters. We have seen +the simplest case of one parameter such as ``range(4)`` which creates ``[0, 1, 2, 3]``. +But what if we really want to have the sequence ``[1, 2, 3, 4]``? +We can do this by using a two parameter version of ``range`` where the first parameter is the starting point and the second parameter is the ending point. The evaluation of ``range(1,5)`` produces the desired sequence. What happened to the 5? +In this case we interpret the parameters of the range function to mean +range(start,beyondLast), where beyondLast means an index past the last index we want. In the 2-parameter version +of range, that is the last index included + 1. + + +.. note:: + + Why in the world would range not just work like range(start, + stop)? Think about it like this. Because computer scientists like to + start counting at 0 instead of 1, ``range(N)`` produces a sequence of + things that is N long, but the consequence of this is that the final + number of the sequence is N-1. In the case of start, + stop it helps to simply think that the sequence begins with start and + continues as long as the number is less than stop. + +.. note:: + The range function is *lazy*: It produces the next element only when needed. + With a regular Python 3 interpreter, printing a range does *not* calculate all the elements. + To immediately calculate all the elements in a range, + wrap the range in a list, like ``list(range(4))``. + Activecode is not designed to work on very long sequences, and it may allow you to be + sloppy, avoiding the list function, and *see* the elements in the range with ``print(range(4))``. + +Here are two examples for you to run. Try them and then add another line below to create a sequence starting +at 10 and going up to 20 (including 20). + +.. activecode:: ch03_5 + :nocanvas: + + print(list(range(4))) + print(list(range(1, 5))) + + +Codelens will help us to further understand the way range works. In this case, the variable ``i`` will take on values +produced by the ``range`` function. + +.. codelens:: rangeme + + for i in range(10): + print(i) + + + +Finally, suppose we want to actually count down from 10 to 1. +How would we do that? Easy, we add another parameter, a step, +that tells range what to count by. For our purposes, we want to start at 10 +and count down by 1 each time. So if we wanted 10 numbers counting down we would use +``range(10,0,-1)``. The most general form of the range is +``range(start, beyondLast, step)``. You can also create a sequence of numbers that +skips some using a step size larger than 1 or smaller than -1. + +.. activecode:: ch03_6 + :nocanvas: + + print(list(range(0, 19, 2))) + print(list(range(0, 20, 2))) + print(list(range(10, 0, -1))) + +Try it in codelens. Do you see why the first two statements produce the same result? + + +.. codelens:: rangeme2 + + for i in range(0, 20, 2): + print(i) + +**Check your understanding** + +.. mchoice:: test_question3_5_1 + :practice: T + :answer_a: Range should generate a sequence that stops before 10 (including 9). + :answer_b: Range should generate a sequence that starts at 10 (including 10). + :answer_c: Range should generate a sequence starting at 3 that stops at 10 (including 10). + :answer_d: Range should generate a sequence using every 10th number between the start and the stopping number. + :correct: a + :feedback_a: Range will generate the sequence 3, 5, 7, 9. + :feedback_b: The first argument (3) tells range what number to start at. + :feedback_c: Range will always stop at the number in the sequence before (not including) the specified limit for the sequence. + :feedback_d: The third argument (2) tells range how many numbers to skip between each element in the sequence. + + In the command range(3, 10, 2), what does the second argument (10) specify? + +.. mchoice:: test_question3_5_2 + :practice: T + :answer_a: range(2, 5, 8) + :answer_b: range(2, 8, 3) + :answer_c: range(2, 10, 3) + :answer_d: range(8, 1, -3) + :correct: c + :feedback_a: This command generates the sequence with just the number 2 because the first parameter (2) tells range where to start, the second number tells range where to end (before 5) and the third number tells range how many numbers to skip between elements (8). Since 10 >= 5, there is only one number in this sequence. + :feedback_b: This command generates the sequence 2, 5 because 8 is not less than 8 (the specified number past the end). + :feedback_c: The first number is the starting point, the second is past the last allowed, and the third is the amount to increment by. + :feedback_d: This command generates the sequence 8, 5, 2 because it starts at 8, ends before 1, and skips to every third number going down. + + What command correctly generates the sequence 2, 5, 8? + +.. mchoice:: test_question3_5_3 + :practice: T + :answer_a: It will generate a sequence starting at 0, with every number included up to but not including the argument it was passed. + :answer_b: It will generate a sequence starting at 1, with every number up to but not including the argument it was passed. + :answer_c: It will generate a sequence starting at 1, with every number including the argument it was passed. + :answer_d: It will cause an error: range always takes exactly 3 arguments. + :correct: a + :feedback_a: Yes, if you only give one number to range it starts with 0 and ends before the number specified incrementing by 1. + :feedback_b: Range with one parameter starts at 0. + :feedback_c: Range with one parameter starts at 0, and never includes the argument it was passed. + :feedback_d: If range is passed only one argument, it interprets that argument as one past the end of the list. + + What happens if you give range only one argument? For example: range(4) + +.. mchoice:: test_question3_5_4 + :practice: T + :answer_a: range(5, 25, 5) + :answer_b: range(20, 3, -5) + :answer_c: range(20, 5, 4) + :answer_d: range(20, 5, -5) + :correct: b + :feedback_a: The step 5 is positive, while the given sequence is decreasing. This answer creates the reversed, increasing sequence. + :feedback_b: Yes: If we take steps of -5, not worrying about the ending, we get 20, 15, 10, 5, 0, .... The limit 3 is past the 5, so the range sequence stops with the 5. + :feedback_c: The step 5 is positive so the sequence would need to increase from 20 toward 4. That does not make sense and the sequence would be empty. + :feedback_d: the sequence can never include the second parameter (5). The second parameter must always be past the end of the range sequence. + + Which range function call will produce the sequence 20, 15, 10, 5? + + +.. mchoice:: test_question3_5_5 + :practice: T + :answer_a: No other value would give the same sequence. + :answer_b: The only other choice is 14. + :answer_c: 11, 13, or 14 + :correct: c + :feedback_a: The sequence produced has steps of 4: 2, 6, 10. The next would be 14, but it is not before the limit 12. There are other limit choices past 10, but not past 14. + :feedback_b: 14 would work: It is also past 10, and not past 14, but there are other integers with the same properties. + :feedback_c: Yes, any integer past 10, and not past the next step at 14 would work. + + What could the second parameter (12) in range(2, 12, 4) be replaced with and generate exactly the same sequence? diff --git a/_sources/MoreAboutIteration/ThewhileStatement.rst b/_sources/MoreAboutIteration/ThewhileStatement.rst index 201fdfc99..e0f91cc24 100644 --- a/_sources/MoreAboutIteration/ThewhileStatement.rst +++ b/_sources/MoreAboutIteration/ThewhileStatement.rst @@ -20,75 +20,37 @@ The ``while`` Statement :width: 560 :align: left -There is another Python statement that can also be used to build an iteration. It is called the ``while`` statement. -The ``while`` statement provides a much more general mechanism for iterating. Similar to the ``if`` statement, it uses -a boolean expression to control the flow of execution. The body of while will be repeated as long as the controlling boolean expression evaluates to ``True``. +A basic building block of all programs is to be able to repeat some code +over and over again. In computer science, we refer to this repetitive idea as **iteration**. In this section, we will explore some mechanisms for basic iteration. -The following figure shows the flow of control. - -.. image:: Figures/while_flow.png - -We can use the ``while`` loop to create any type of iteration we wish, including anything that we have previously done with a ``for`` loop. For example, the program in the previous section could be rewritten using ``while``. -Instead of relying on the ``range`` function to produce the numbers for our summation, we will need to produce them ourselves. To to this, we will create a variable called ``aNumber`` and initialize it to 1, the first number in the summation. Every iteration will add ``aNumber`` to the running total until all the values have been used. -In order to control the iteration, we must create a boolean expression that evaluates to ``True`` as long as we want to keep adding values to our running total. In this case, as long as ``aNumber`` is less than or equal to the bound, we should keep going. - - - -Here is a new version of the summation program that uses a while statement. +Let's look at our first Python statement that can be used to build an iteration. It is called the ``while`` statement. When used with other code it can be used to +repeat code in a **while loop**. Similar to the ``if`` statement, it uses +a boolean expression to control the flow of execution. The body of while (code indented one space in) will be repeated as long as the controlling boolean +expression evaluates to ``True``. +Here is a simple example that counts down from 10 to 0. .. activecode:: ch07_while1 - def sumTo(aBound): - """ Return the sum of 1+2+3 ... n """ - - theSum = 0 - aNumber = 1 - while aNumber <= aBound: - theSum = theSum + aNumber - aNumber = aNumber + 1 - return theSum - - print(sumTo(4)) - - print(sumTo(1000)) - - - -You can almost read the ``while`` statement as if it were in natural language. It means, -while ``aNumber`` is less than or equal to ``aBound``, continue executing the body of the loop. Within -the body, each time, update ``theSum`` using the accumulator pattern and increment ``aNumber``. After the body of the loop, we go back up to the condition of the ``while`` and reevaluate it. When ``aNumber`` becomes greater than ``aBound``, the condition fails and flow of control continues to the ``return`` statement. - -The same program in codelens will allow you to observe the flow of execution. - -.. codelens:: ch07_while2 - - def sumTo(aBound): - """ Return the sum of 1+2+3 ... n """ - - theSum = 0 - aNumber = 1 - while aNumber <= aBound: - theSum = theSum + aNumber - aNumber = aNumber + 1 - return theSum - - print(sumTo(4)) - - - -More formally, here is the flow of execution for a ``while`` statement: - -#. Evaluate the condition, yielding ``False`` or ``True``. -#. If the condition is ``False``, exit the ``while`` statement and continue - execution at the next statement. -#. If the condition is ``True``, execute each of the statements in the body and - then go back to step 1. - -The body consists of all of the statements below the header with the same -indentation. - -This type of flow is called a **loop** because the third step loops back around -to the top. Notice that if the condition is ``False`` the first time through the + count = 10 + while count > 0: + print(count) + count = count - 1 + print("Blastoff!") + +* **count** is a normal variable here, but since it is governing the ``while`` loop it is also called the **loop variable**. +* Line 2 here is the *loop condition**. It must always be a boolean expression that will evaluate to ``False`` or ``True``. +* Lines 3 and 4 are the **loop body**. The loop body is always + indented. The indentation determines exactly what statements are "in the + loop". The loop body is run each time the loop is repeated. +* On each *iteration* or *pass* of the loop, a check is done to see if + the loop condition is True (if ``count`` is greater than zero). If it is not (this is + called the **terminating condition** of the loop), the loop has finished. + Program execution continues at the next statement after the loop body. +* If ``count`` is greater than zero, the loop body is executed again. +* At the end of each execution of the body of the loop, Python returns + to the ``while`` statement, to see if the loop should repeat. + +Notice that if the condition is ``False`` the first time through the loop, the statements inside the loop are never executed. .. warning:: @@ -102,51 +64,63 @@ loop, the statements inside the loop are never executed. The body of the loop should change the value of one or more variables so that eventually the condition becomes ``False`` and the loop terminates. Otherwise the loop will repeat forever. This is called an **infinite loop**. -An endless -source of amusement for computer scientists is the observation that the +An endless source of amusement for computer scientists is the observation that the directions written on the back of the shampoo bottle (lather, rinse, repeat) create an infinite loop. -In the case shown above, we can prove that the loop terminates because we -know that the value of ``aBound`` is finite, and we can see that the value of ``aNumber`` -increments each time through the loop, so eventually it will have to exceed ``aBound``. In -other cases, it is not so easy to tell. +We can use the ``while`` loop to create any type of iteration we wish, making more general-purpose than the ``for`` loop we'll learn next week. +For example, let us consider a program that adds all numbers from ``1`` to ``n``. To do this, we will create a variable called ``aNumber`` and initialize it to +1, the first number in the summation. Every iteration will add ``aNumber`` to the running total until all the values have been used. +In order to control the iteration, we must create a boolean expression that evaluates to ``True`` as long as we want to keep adding values to our +running total. In this case, as long as ``aNumber`` is less than or equal to the bound, we should keep going. -.. note:: +Here is the summation program that uses a while statement. - Introduction of the while statement causes us to think about the types of iteration we have seen. The ``for`` statement will always iterate through a sequence of values like the list of names for the party or the list of numbers created by ``range``. Since we know that it will iterate once for each value in the collection, it is often said that a ``for`` loop creates a - **definite iteration** because we definitely know how many times we are going to iterate. On the other - hand, the ``while`` statement is dependent on a condition that needs to evaluate to ``False`` in order - for the loop to terminate. Since we do not necessarily know when this will happen, it creates what we - call **indefinite iteration**. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition controlling the iteration will fail and the iteration will stop. (Unless we have an infinite loop which is of course a problem.) +.. activecode:: ch07_while2 -What you will notice here is that the ``while`` loop is more work for -you --- the programmer --- than the equivalent ``for`` loop. When using a ``while`` -loop you have to control the loop variable yourself. You give it an initial value, test -for completion, and then make sure you change something in the body so that the loop -terminates. + """ Return the sum of 1+2+3 ... n """ + + aBound = int(input("Please give a number n: ")) + theSum = 0 + aNumber = 1 + while aNumber <= aBound: + theSum = theSum + aNumber + aNumber = aNumber + 1 + print(theSum) -So why have two kinds of loop if ``for`` looks easier? The next section, :ref:`randomly-walking-turtles`, shows an indefinite iteration where -we need the extra power that we get from the ``while`` loop. -.. note:: +You can almost read the ``while`` statement as if it were in natural language. It means, +while ``aNumber`` is less than or equal to ``aBound``, continue executing the body of the loop. Within +the body, each time, update ``theSum`` and increment ``aNumber``. After the body of the loop, we go +back up to the condition of the ``while`` and reevaluate it. When ``aNumber`` becomes greater +than ``aBound``, the condition fails and flow of control continues to the ``print`` statement. - This workspace is provided for your convenience. You can use this activecode window to try out anything you like. +The same program in codelens will allow you to observe the flow of execution. - .. activecode:: scratch_07_01 +.. codelens:: ch07_while3 + """ Return the sum of 1+2+3 ... n """ + + aBound = int(input("Please give a number n: ")) + theSum = 0 + aNumber = 1 + while aNumber <= aBound: + theSum = theSum + aNumber + aNumber = aNumber + 1 + print(theSum) -**Check your understanding** -.. mchoice:: test_question7_2_1 - :practice: T - :answer_a: True - :answer_b: False - :correct: a - :feedback_a: Although the while loop uses a different syntax, it is just as powerful as a for-loop and often more flexible. - :feedback_b: Often a for-loop is more natural and convenient for a task, but that same task can always be expressed using a while loop. - True or False: You can rewrite any for-loop as a while-loop. +In the case shown above, we can prove that the loop terminates because we +know that the value of ``aBound`` is finite, and we can see that the value of ``aNumber`` +increments each time through the loop, so eventually it will have to exceed ``aBound``. In +other cases, it is not so easy to tell. + +.. note:: + + This workspace is provided for your convenience. You can use this activecode window to try out anything you like. + + .. activecode:: scratch_07_01 .. mchoice:: test_question7_2_2 :practice: T diff --git a/_sources/MoreAboutIteration/intro-IterationRevisited.rst b/_sources/MoreAboutIteration/intro-IterationRevisited.rst index fac46c62c..e1e91716a 100644 --- a/_sources/MoreAboutIteration/intro-IterationRevisited.rst +++ b/_sources/MoreAboutIteration/intro-IterationRevisited.rst @@ -11,7 +11,7 @@ :prefix: iter-1- :start: 1 -Iteration Revisited +Iteration =================== .. index:: iteration, assignment, assignment statement, reassignment @@ -26,10 +26,8 @@ people do poorly. Repeated execution of a sequence of statements is called **iteration**. Because iteration is so common, Python provides several language features to make it -easier. We've already seen the ``for`` statement in a previous chapter. This is a very common -form of iteration in Python. In this chapter -we are going to look at the ``while`` statement --- another way to have your -program do iteration. +easier. In this chapter we are going to look at two common forms of iteration: the ``while`` statement +and the ``for`` statement. .. index:: for loop diff --git a/_sources/MoreAboutIteration/toctree.rst b/_sources/MoreAboutIteration/toctree.rst index 6b944d8ff..6e1842939 100644 --- a/_sources/MoreAboutIteration/toctree.rst +++ b/_sources/MoreAboutIteration/toctree.rst @@ -1,18 +1,21 @@ -More About Iteration +Iteration :::::::::::::::::::: .. toctree:: - :caption: More About Iteration + :caption: Iteration :maxdepth: 2 - intro-IterationRevisited.rst - Theforlooprevisited.rst + intro-Iteration.rst ThewhileStatement.rst - RandomlyWalkingTurtles.rst + FlowofExecutionofthewhileLoop.rst The3n1Sequence.rst + SentinelValuesAndValidation.rst + + TheforLoop.rst + TherangeFunction.rst NewtonsMethod.rst accumulatorRevisited.rst - SentinelValuesAndValidation.rst + AlgorithmsRevisited.rst SimpleTables.rst 2DimensionalIterationImageProcessing.rst diff --git a/_sources/Selection/ConditionalExecutionBinarySelection.rst b/_sources/Selection/ConditionalExecutionBinarySelection.rst index 76ab28dcc..20ac98a18 100644 --- a/_sources/Selection/ConditionalExecutionBinarySelection.rst +++ b/_sources/Selection/ConditionalExecutionBinarySelection.rst @@ -56,14 +56,22 @@ indented under the ``else`` clause get executed. .. image:: Figures/flowchart_if_else.png - - -As with the function definition from the last chapter and other compound -statements like ``for``, the ``if`` statement consists of a header line and a body. The header +As a program executes, the interpreter always keeps track of which statement is +about to be executed. We call this the **control flow**, or the **flow of +execution** of the program. When humans execute programs, they often use their +finger to point to each statement in turn. So you could think of control flow +as "Python's moving finger". + +Control flow until now has been strictly top to bottom, one statement at a +time. We call this type of control **sequential**. In Python flow is sequential as long as +successive statements are indented the *same* amount. The ``if`` statement +introduces indented sub-statements after the if heading. + +Each ``if`` statement consists of a header line and a body. The header line begins with the keyword ``if`` followed by a *boolean expression* and ends with a colon (:). -The more indented statements that follow are called a **block**. +The more indented statements that follow are called a **block** or sometimes a **body**. Each of the statements inside the first block of statements is executed in order if the boolean expression evaluates to ``True``. The entire first block of statements From 139401f3e81d44564f187d8147e1b8383c31010e Mon Sep 17 00:00:00 2001 From: robotuw Date: Mon, 20 Feb 2023 16:01:11 -0700 Subject: [PATCH 12/90] Weeks 7 and 8 Update Another set of reordering and content changes for class weeks seven and eight specifically. Concerns mostly functions and modules chapters. --- .error_schema.log | 2 + .gitignore-20230129-131712 | 91 +++++++++ .../Functionscancallotherfunctions.rst | 95 ---------- .../Functions/Functionsthatreturnvalues.rst | 23 +-- _sources/Functions/functions.rst | 179 ++++++------------ _sources/Functions/mainfunction.rst | 68 +++---- _sources/Functions/toctree.rst | 3 +- _sources/Lists/toctree.rst | 3 +- .../FlowofExecutionofthewhileLoop.rst | 27 +-- _sources/MoreAboutIteration/NewtonsMethod.rst | 40 ++-- .../SentinelValuesAndValidation.rst | 14 +- .../MoreAboutIteration/The3n1Sequence.rst | 20 +- _sources/MoreAboutIteration/TheforLoop.rst | 19 +- .../MoreAboutIteration/ThewhileStatement.rst | 21 +- _sources/PythonModules/CreatingModules.rst | 6 +- .../PythonModules/MoreAboutUsingModules.rst | 16 +- _sources/PythonModules/modules.rst | 28 ++- _sources/PythonModules/toctree.rst | 1 - _sources/Strings/toctree.rst | 5 +- _sources/index.rst | 4 +- cli.log | 7 + project-20230129-131712.ptx | 51 +++++ publication/publication.ptx | 7 + requirements-20230129-131712.txt | 1 + 24 files changed, 337 insertions(+), 394 deletions(-) create mode 100644 .error_schema.log create mode 100644 .gitignore-20230129-131712 create mode 100644 cli.log create mode 100644 project-20230129-131712.ptx create mode 100644 publication/publication.ptx create mode 100644 requirements-20230129-131712.txt diff --git a/.error_schema.log b/.error_schema.log new file mode 100644 index 000000000..2a12b54b8 --- /dev/null +++ b/.error_schema.log @@ -0,0 +1,2 @@ +file:/C:/Users/Rob/Documents/GitHub/thinkcspy/pretext/thinkcspy.ptx:3:0:ERROR:RELAXNGV:RELAXNG_ERR_ELEMWRONG: Did not expect element include there +file:/C:/Users/Rob/Documents/GitHub/thinkcspy/pretext/thinkcspy.ptx:3:0:ERROR:RELAXNGV:RELAXNG_ERR_EXTRACONTENT: Element pretext has extra content: include \ No newline at end of file diff --git a/.gitignore-20230129-131712 b/.gitignore-20230129-131712 new file mode 100644 index 000000000..ed41bfbfe --- /dev/null +++ b/.gitignore-20230129-131712 @@ -0,0 +1,91 @@ +# Boilerplate list of files in a PreTeXt project for git to ignore +# ensure this file is tracked +!.gitignore + +# don't track unpublished builds +output + +# don't track assets generated from source +generated-assets + +# don't track node packages +node_modules + +# don't track error logs +.error_schema.log +cli.log + +# don't track OS related files (windows/macos/linux) +.DS_Store +.DS_Store? +._* +.AppleDouble +.LSOverride +.Spotlight-V100 +.Trashes +Icon +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +*.lnk +*.cab +*.msi +*.msix +*.msm +*.msp +[Dd]esktop.ini +.directory +.fuse_hidden* +.Trash-* +.nfs* + +# Don't include VSCode generated files +.vscode +*.code-workspace + +# Don't inlucde SublimeText files +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +*.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +# Don't include Dropbox settings and caches +.dropbox +.dropbox.attr +.dropbox.cache + diff --git a/_sources/Functions/Functionscancallotherfunctions.rst b/_sources/Functions/Functionscancallotherfunctions.rst index 726f70981..28062ce48 100644 --- a/_sources/Functions/Functionscancallotherfunctions.rst +++ b/_sources/Functions/Functionscancallotherfunctions.rst @@ -62,94 +62,6 @@ for ``sum_of_squares``. As you step through you will notice that ``x``, and ``y different values. This illustrates that even though they are named the same, they are in fact, very different. -Now we will look at another example that uses two functions. This example illustrates an -important computer science problem solving technique called -**generalization**. Assume we want to write a -function to draw a square. The generalization step is to realize that a -square is just a special kind of rectangle. - -To draw a rectangle we need to be able to call a function with different -arguments for width and height. Unlike the case of the square, -we cannot repeat the same thing 4 times, because the four sides are not equal. -However, it is the case that drawing the bottom and right sides are the -same sequence as drawing the top and left sides. So we eventually come up with -this rather nice code that can draw a rectangle. - -.. code-block:: python - - def drawRectangle(t, w, h): - """Get turtle t to draw a rectangle of width w and height h.""" - for i in range(2): - t.forward(w) - t.left(90) - t.forward(h) - t.left(90) - -The parameter names are chosen as single letters for conciseness. -In real programs, we will insist on better variable names than this. -The point is that the program doesn't "understand" that you're drawing a rectangle or that the -parameters represent the width and the height. Concepts like rectangle, width, and height are meaningful -for humans. They are not concepts that the program or the computer understands. - -*Thinking like a computer scientist* involves looking for patterns and -relationships. In the code above, we've done that to some extent. We did -not just draw four sides. Instead, we spotted that we could draw the -rectangle as two halves and used a loop to repeat that pattern twice. - -But now we might spot that a square is a special kind of rectangle. A square -simply uses the same value for both the height and the width. -We already have a function that draws a rectangle, so we can use that to draw -our square. - -.. code-block:: python - - def drawSquare(tx, sz): # a new version of drawSquare - drawRectangle(tx, sz, sz) - -Here is the entire example with the necessary set up code. - -.. activecode:: ch04_3 - :nocodelens: - - import turtle - - def drawRectangle(t, w, h): - """Get turtle t to draw a rectangle of width w and height h.""" - for i in range(2): - t.forward(w) - t.left(90) - t.forward(h) - t.left(90) - - def drawSquare(tx, sz): # a new version of drawSquare - drawRectangle(tx, sz, sz) - - wn = turtle.Screen() # Set up the window - wn.bgcolor("lightgreen") - - tess = turtle.Turtle() # create tess - - drawSquare(tess, 50) - - wn.exitonclick() - - - -There are some points worth noting here: - -* Functions can call other functions. -* Rewriting ``drawSquare`` like this captures the relationship - that we've spotted. -* A caller of this function might say ``drawSquare(tess, 50)``. The parameters - of this function, ``tx`` and ``sz``, are assigned the values of the tess object, and - the integer 50 respectively. -* In the body of the function, ``tz`` and ``sz`` are just like any other variable. -* When the call is made to ``drawRectangle``, the values in variables ``tx`` and ``sz`` - are fetched first, then the call happens. So as we enter the top of - function ``drawRectangle``, its variable ``t`` is assigned the tess object, and ``w`` and - ``h`` in that function are both given the value 50. - - So far, it may not be clear why it is worth the trouble to create all of these new functions. Actually, there are a lot of reasons, but this example demonstrates two: @@ -163,10 +75,3 @@ demonstrates two: #. Sometimes you can write functions that allow you to solve a specific problem using a more general solution. - -.. admonition:: Lab - - * `Drawing a Circle <../Labs/lab04_01.html>`_ In this guided lab exercise we will work - through a simple problem solving exercise related to drawing a circle with the turtle. - - diff --git a/_sources/Functions/Functionsthatreturnvalues.rst b/_sources/Functions/Functionsthatreturnvalues.rst index 51a0fa55c..cae049591 100644 --- a/_sources/Functions/Functionsthatreturnvalues.rst +++ b/_sources/Functions/Functionsthatreturnvalues.rst @@ -32,9 +32,7 @@ the absolute value: In this example, the arguments to the ``abs`` function are 5 and -5. -Some functions take more than one argument. For example the math module contains a function -called -``pow`` which takes two arguments, the base and the exponent. +Some functions take more than one argument. For example the range function that we saw with ``for`` loops. .. Inside the function, .. the values that are passed get assigned to variables called **parameters**. @@ -42,14 +40,9 @@ called .. activecode:: ch04_5 :nocanvas: - import math - print(math.pow(2, 3)) + print(list(range(4, 8))) - print(math.pow(7, 4)) - -.. note:: - - Of course, we have already seen that raising a base to an exponent can be done with the ** operator. + print(list(range(1, 10))) Another built-in function that takes more than one argument is ``max``. @@ -65,17 +58,17 @@ return the maximum value sent. The arguments can be either simple values or expressions. In the last example, 503 is returned, since it is larger than 33, 125, and 1. Note that ``max`` also works on lists of values. -Furthermore, functions like ``range``, ``int``, ``abs`` all return values that +Furthermore, functions like ``int``, ``abs`` all return values that can be used to build more complex expressions. .. index:: fruitful function variable; global global variable -So an important difference between these functions and one like ``drawSquare`` is that -``drawSquare`` was not executed because we wanted it to compute a value --- on the contrary, -we wrote ``drawSquare`` because we wanted it to execute a sequence of steps that caused -the turtle to draw a specific shape. +So an important difference between these functions and one like ``printRange`` is that +``printRange`` was not executed because we wanted it to compute a value --- on the contrary, +we wrote ``printRange`` because we wanted it to execute a sequence of steps that caused +the list's range to print. Functions that return values are sometimes called **fruitful functions**. In many other languages, a chunk that doesn't return a value is called a **procedure**, diff --git a/_sources/Functions/functions.rst b/_sources/Functions/functions.rst index 1d1380e0b..879251e0c 100644 --- a/_sources/Functions/functions.rst +++ b/_sources/Functions/functions.rst @@ -55,7 +55,7 @@ pattern: indented the same amount -- *4 spaces is the Python standard* -- from the header line. -We've already seen the ``for`` loop which follows this pattern. +We've already seen the ``while`` and ``for`` loops which follow this pattern. In a function definition, the keyword in the header is ``def``, which is followed by the name of the function and some *parameters* enclosed in @@ -72,37 +72,27 @@ The figure below shows this relationship. A function needs certain information This type of diagram is often called a **black-box diagram** because it only states the requirements from the perspective of the user. The user must know the name of the function and what arguments need to be passed. The details of how the function works are hidden inside the "black-box". -Suppose we're working with turtles and a common operation we need is to draw -squares. It would make sense if we did not have to duplicate all the steps each time we want to make a square. "Draw a square" can be thought of as an *abstraction* of a number of smaller steps. We will need to provide two pieces of information for the function to do its work: a turtle to do the drawing and a size for the side of the square. We could represent this using the following black-box diagram. - -.. image:: Figures/turtleproc.png +Suppose we're working with lists of numeric data and a common operation we need is to find the size of the range of numbers in a list. +It would make sense if we did not have to duplicate all the steps each time we want to find the size of the range. "printRange" can be thought of as an +*abstraction* of a number of smaller steps. We will need to provide one piece of information for the function to do its work: the list we need the range of. Here is a program containing a function to capture this idea. Give it a try. .. activecode:: ch04_1 :nocodelens: - import turtle - - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - - for i in range(4): - t.forward(sz) - t.left(90) - - - wn = turtle.Screen() # Set up the window and its attributes - wn.bgcolor("lightgreen") + def printRange(lst): + """Prints the size of the range of lst.""" + smallest = min(lst) + largest = max(lst) + print(largest - smallest) - alex = turtle.Turtle() # create alex - drawSquare(alex, 50) # Call the function to draw the square passing the actual turtle and the actual side size - wn.exitonclick() + my_list1 = [1, 2, 3, 4, 5, 6] + printRange(my_list1) -This function is named ``drawSquare``. It has two parameters --- one to tell -the function which turtle to move around and the other to tell it the size -of the square we want drawn. In the function definition they are called ``t`` and ``sz`` respectively. Make sure you know where the body of the function +This function is named ``printRange``. It has one parameter --- a variable storing a list of numbers. In the function definition this parameter is called +``lst``. Make sure you know where the body of the function ends --- it depends on the indentation and the blank lines don't count for this purpose! @@ -129,9 +119,8 @@ Defining a new function does not make the function run. To do that we need a ``print``, ``range`` and ``int``. Function calls contain the name of the function to be executed followed by a list of values in parentheses, called *arguments*, which are assigned to the parameters in the function definition. -So in the second to the last line of -the program, we call the function, and pass ``alex`` as the turtle to be manipulated, -and 50 as the size of the square we want. +So in the last line of +the program, we call the function, and pass ``my_list1`` as the list to be analyzed. .. The parameters being sent to the function, sometimes referred to as the **actual parameters** or **arguments**, .. represent the specific data items that the function will use when it is executing. @@ -142,67 +131,24 @@ and 50 as the size of the square we want. Once we've defined a function, we can call it as often as we like and its statements will be executed each time we call it. In this case, we could use it to get -one of our turtles to draw a square and then we can move the turtle and have it draw a different square in a -different location. Note that we lift the tail so that when ``alex`` moves there is no trace. We put the tail -back down before drawing the next square. Make sure you can identify both invocations of the ``drawSquare`` function. - -.. activecode:: ch04_1a - :nocodelens: - - import turtle - - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - - for i in range(4): - t.forward(sz) - t.left(90) +the size of the range of multiple lists. Make sure you can identify all three invocations of the ``printRange`` function. - - wn = turtle.Screen() # Set up the window and its attributes - wn.bgcolor("lightgreen") - - alex = turtle.Turtle() # create alex - drawSquare(alex, 50) # Call the function to draw the square - - alex.penup() - alex.goto(100,100) - alex.pendown() - - drawSquare(alex,75) # Draw another square - - wn.exitonclick() - -In the next example, we've changed the ``drawSquare`` -function a little and we get ``tess`` to draw 15 squares with some variations. Once the function has -been defined, we can call it as many times as we like with whatever actual parameters we like. - -.. activecode:: ch04_2 +.. activecode:: ch04_1 :nocodelens: - import turtle - - def drawMulticolorSquare(t, sz): - """Make turtle t draw a multi-colour square of sz.""" - for i in ['red','purple','hotpink','blue']: - t.color(i) - t.forward(sz) - t.left(90) - - wn = turtle.Screen() # Set up the window and its attributes - wn.bgcolor("lightgreen") + def printRange(lst): + """Prints the size of the range of lst.""" + smallest = min(lst) + largest = max(lst) + print(largest - smallest) - tess = turtle.Turtle() # create tess and set some attributes - tess.pensize(3) - size = 20 # size of the smallest square - for i in range(15): - drawMulticolorSquare(tess, size) - size = size + 10 # increase the size for next time - tess.forward(10) # move tess along a little - tess.right(18) # and give her some extra turn + my_list1 = [1, 2, 3, 4, 5, 6] + my_list2 = [2, 6, 9, 16, 42, 100, 2, 5] + printRange(my_list1) + printRange(my_list2) + printRange([5, 10, 1000, 2]) - wn.exitonclick() .. warning:: @@ -210,8 +156,8 @@ been defined, we can call it as many times as we like with whatever actual param the parentheses ``( )`` after the function name are *required*. This can lead to a difficult bug: A function name without the parenthesis is a legal expression *referring* to the function; for example, - ``print`` and ``alex.penup``, but they do - not *call* the associated functions. + ``print``, but it does + not *call* the associated function. Try it below if you want to see. .. note:: @@ -267,10 +213,10 @@ been defined, we can call it as many times as we like with whatever actual param .. mchoice:: test_question5_1_4 :practice: T - :answer_a: def drawSquare(t, sz) - :answer_b: drawSquare - :answer_c: drawSquare(t, sz) - :answer_d: Make turtle t draw a square with side sz. + :answer_a: def printSquare(size) + :answer_b: printSquare + :answer_c: printSquare(size) + :answer_d: Print a square of asterices with side size. :correct: b :feedback_a: This line is the complete function header (except for the semi-colon) which includes the name as well as several other components. :feedback_b: Yes, the name of the function is given after the keyword def and before the list of parameters. @@ -281,61 +227,58 @@ been defined, we can call it as many times as we like with whatever actual param .. code-block:: python - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - for i in range(4): - t.forward(sz) - t.left(90) + def printSquare(size): + """Print a square of asterices with side size.""" + for i in range(size): + print("*"*size) .. mchoice:: test_question5_1_5 :practice: T :answer_a: i - :answer_b: t - :answer_c: t, sz - :answer_d: t, sz, i + :answer_b: size, i + :answer_c: size + :answer_d: "*"*size :correct: c :feedback_a: i is a variable used inside of the function, but not a parameter, which is passed in to the function. - :feedback_b: t is only one of the parameters to this function. - :feedback_c: Yes, the function specifies two parameters: t and sz. - :feedback_d: the parameters include only those variables whose values that the function expects to receive as input. They are specified in the header of the function. + :feedback_b: i is a variable used inside of the function, but not a parameter, which is passed in to the function. + :feedback_c: Yes, the function specifies one parameter: size. + :feedback_d: This is an argument provided to the call to print(). What are the parameters of the following function? .. code-block:: python - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - for i in range(4): - t.forward(sz) - t.left(90) + def printSquare(size): + """Print a square of asterices with side size.""" + for i in range(size): + print("*"*size) .. mchoice:: test_question5_1_6 :practice: T - :answer_a: def drawSquare(t, sz) - :answer_b: drawSquare - :answer_c: drawSquare(10) - :answer_d: drawSquare(alex, 10): - :answer_e: drawSquare(alex, 10) + :answer_a: def printSquare(size) + :answer_b: printSquare + :answer_c: printSquare(10) + :answer_d: printSquare(my_size): + :answer_e: printSquare(size): :correct: e - :feedback_a: No, t and sz are the names of the formal parameters to this function. When the function is called, it requires actual values to be passed in. + :feedback_a: No, size is the name of the formal parameter to this function. When the function is called, it requires an actual value to be passed in. :feedback_b: A function call always requires parentheses after the name of the function. - :feedback_c: This function takes two parameters (arguments) - :feedback_d: A colon is only required in a function definition. It will cause an error with a function call. - :feedback_e: Since alex was already previously defined and 10 is a value, we have passed in two correct values for this function. + :feedback_c: Yes, this would work + :feedback_d: Yes, this would work since my_size is already defined. + :feedback_e: A colon is only required in a function definition. It will cause an error with a function call. - Considering the function below, which of the following statements correctly invokes, or calls, this function (i.e., causes it to run)? Assume we already have a turtle named alex. + Considering the function below, which of the following statements correctly invokes, or calls, this function (i.e., causes it to run)? Assume we already have a variable named my_size. .. code-block:: python - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - for i in range(4): - t.forward(sz) - t.left(90) + def printSquare(size): + """Print a square of asterices with side size.""" + for i in range(size): + print("*"*size) diff --git a/_sources/Functions/mainfunction.rst b/_sources/Functions/mainfunction.rst index addbdf8f0..9128bfabd 100644 --- a/_sources/Functions/mainfunction.rst +++ b/_sources/Functions/mainfunction.rst @@ -19,65 +19,54 @@ Using a Main Function --------------------- Using functions is a good idea. It helps us to modularize our code by breaking a program -into logical parts where each part is responsible for a specific task. For example, in one of our first programs there -was a function called ``drawSquare`` that was responsible for having some turtle draw a square of some size. -The actual turtle and the actual size of the square were defined to be provided as parameters. Here is that original program. +into logical parts where each part is responsible for a specific task. For example, in one of our recent programs there +was a function called ``square`` that was responsible for calculating the square of a number. +After the function definition we defined a variable, called the function, and printed its results. Here is that original program. .. code-block:: python - import turtle + def square(x): + y = x * x + return y - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" + toSquare = 10 + squareResult = square(toSquare) + print("The result of", toSquare, "squared is", squareResult) - for i in range(4): - t.forward(sz) - t.left(90) +If you look closely at the structure of this program, we first define the function ``square``. At this point, we could have defined as many functions as were needed. Finally, there are five statements that set up the window, create the turtle, perform the function invocation, and wait for a user click to terminate the program. - wn = turtle.Screen() # Set up the window and its attributes - wn.bgcolor("lightgreen") +The final three statements perform the main processing that the program will do. Notice that much of the detail has been pushed inside the ``square`` function. +However, there are still these three lines of code that are needed to get things done. - alex = turtle.Turtle() # create alex - drawSquare(alex, 50) # Call the function to draw the square - - wn.exitonclick() - - -If you look closely at the structure of this program, you will notice that we first perform all of our necessary ``import`` statements, in this case to be able to use the ``turtle`` module. Next, we define the function ``drawSquare``. At this point, we could have defined as many functions as were needed. Finally, there are five statements that set up the window, create the turtle, perform the function invocation, and wait for a user click to terminate the program. - -These final five statements perform the main processing that the program will do. Notice that much of the detail has been pushed inside the ``drawSquare`` function. However, there are still these five lines of code that are needed to get things done. - -In many programming languages (e.g. Java and C++), it is not possible to simply have statements sitting alone like this at the bottom of the program. They are required to be part of a special function that is automatically invoked by the operating system when the program is executed. This special function is called **main**. Although this is not required by the Python programming language, it is actually a good idea that we can incorporate into the logical structure of our program. In other words, these five lines are logically related to one another in that they provide the main tasks that the program will perform. Since functions are designed to allow us to break up a program into logical pieces, it makes sense to call this piece ``main``. +In many programming languages (e.g. Java and C++), it is not possible to simply have statements sitting alone like this at the bottom of the program. +They are required to be part of a special function that is automatically invoked by the operating system when the program is executed. +This special function is called **main**. Although this is not required by the Python programming language, it is actually a good idea that we +can incorporate into the logical structure of our program. In other words, these three lines are logically related to one another in that they provide the +main tasks that the program will perform. Since functions are designed to allow us to break up a program into logical pieces, it makes sense to call this +piece ``main``. The following activecode shows this idea. In line 11 we have defined a new function called ``main`` that doesn't need any parameters. The five lines of main processing are now placed inside this function. Finally, in order to execute that main processing code, we need to invoke the ``main`` function (line 20). When you push run, you will see that the program works the same as it did before. .. activecode:: ch04_1main :nocodelens: - import turtle - - def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - - for i in range(4): - t.forward(sz) - t.left(90) + def square(x): + y = x * x + return y def main(): # Define the main function - wn = turtle.Screen() # Set up the window and its attributes - wn.bgcolor("lightgreen") - - alex = turtle.Turtle() # create alex - drawSquare(alex, 50) # Call the function to draw the square - - wn.exitonclick() + toSquare = 10 + squareResult = square(toSquare) + print("The result of", toSquare, "squared is", squareResult) main() # Invoke the main function -Now our program structure is as follows. First, import any modules that will be required. Second, define any functions that will be needed. Third, define a ``main`` function that will get the process started. And finally, invoke the main function (which will in turn call the other functions as needed). +Now our program structure is as follows. First, import any modules that will be required (you'll read about those in the next chapter). Second, define any functions +that will be needed. Third, define a ``main`` function that will get the process started. And finally, invoke the main function +(which will in turn call the other functions as needed). .. note:: @@ -110,6 +99,3 @@ The activecode below defines two simple functions and a main. Line 12 uses an ``if`` statement to ask about the value of the ``__name__`` variable. If the value is ``"__main__"``, then the ``main`` function will be called. Otherwise, it can be assumed that the program is being imported into another program and we do not want to call ``main`` because that program will invoke the functions as needed. This ability to conditionally execute our main function can be extremely useful when we are writing code that will potentially be used by others. It allows us to include functionality that the user of the code will not need, most often as part of a testing process to be sure that the functions are working correctly. -.. note:: - - In order to conditionally execute the ``main`` function, we used a structure called an ``if`` statement to create what is known as selection. This topic will be studied in much more detail later. diff --git a/_sources/Functions/toctree.rst b/_sources/Functions/toctree.rst index 938d5bffc..d85f7f987 100644 --- a/_sources/Functions/toctree.rst +++ b/_sources/Functions/toctree.rst @@ -7,7 +7,6 @@ Functions functions.rst Functionsthatreturnvalues.rst - UnitTesting.rst Variablesandparametersarelocal.rst TheAccumulatorPattern.rst Functionscancallotherfunctions.rst @@ -15,6 +14,6 @@ Functions mainfunction.rst ProgramDevelopment.rst Composition.rst - ATurtleBarChart.rst + UnitTesting.rst Glossary.rst Exercises.rst diff --git a/_sources/Lists/toctree.rst b/_sources/Lists/toctree.rst index ffd1c81fa..f0bf30178 100644 --- a/_sources/Lists/toctree.rst +++ b/_sources/Lists/toctree.rst @@ -17,11 +17,11 @@ Lists StringsandLists.rst AppendversusConcatenate.rst ListMembership.rst + NestedLists.rst ObjectsandReferences.rst Aliasing.rst CloningLists.rst RepetitionandReferences.rst - TheReturnofLSystems.rst Listsandforloops.rst TheAccumulatorPatternwithLists.rst UsingListsasParameters.rst @@ -29,7 +29,6 @@ Lists WhichisBetter.rst FunctionsthatProduceLists.rst ListComprehensions.rst - NestedLists.rst listTypeConversionFunction.rst TuplesandMutability.rst TupleAssignment.rst diff --git a/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst index 1f8e38d99..a7b30d4af 100644 --- a/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst +++ b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst @@ -16,21 +16,12 @@ Flow of Execution of the while Loop ---------------------------------- +----------------------------------- -As a program executes, the interpreter always keeps track of which statement is -about to be executed. We call this the **control flow**, or the **flow of -execution** of the program. When humans execute programs, they often use their -finger to point to each statement in turn. So you could think of control flow -as "Python's moving finger". +As before with ``if``, loops allow us as programmers to manipulate the control flow of a Python program. +We can now possibly skip a portion of code, or choose to repeat it an indefinite number of times. -Control flow until now has been strictly top to bottom, one statement at a -time. We call this type of control **sequential**. In Python flow is sequential as long as -successive statements are indented the *same* amount. The ``while`` statement -introduces indented sub-statements after the while-loop heading. - -Flow of control is often easy to visualize and understand if we draw a flowchart. -This flowchart shows the exact steps and logic of how the ``while`` statement executes. +The flowchart below provides the general sequence of steps that govern execution of a while loop. .. image:: Figures/while_flow.png :width: 300px @@ -43,10 +34,10 @@ the buttons. You can see the value of ``count`` change as the loop iterates thr .. codelens:: vtest - count = 10 - while count > 0: - print(count) - count = count - 1 - print("Blastoff!") +count = 10 +while count > 0: + print(count) + count = count - 1 +print("Blastoff!") diff --git a/_sources/MoreAboutIteration/NewtonsMethod.rst b/_sources/MoreAboutIteration/NewtonsMethod.rst index ef7c8b4e4..fb99ac735 100644 --- a/_sources/MoreAboutIteration/NewtonsMethod.rst +++ b/_sources/MoreAboutIteration/NewtonsMethod.rst @@ -38,22 +38,22 @@ value whose square root will be approximated. The second is the number of times calculation yielding a better result. .. activecode:: chp07_newtonsdef - - def newtonSqrt(n, howmany): - approx = 0.5 * n - for i in range(howmany): - betterapprox = 0.5 * (approx + n/approx) - approx = betterapprox - return betterapprox - - print(newtonSqrt(100, 10)) - print(newtonSqrt(4, 10)) - print(newtonSqrt(1, 10)) + + n = 100 + howmany = 10 + + approx = 0.5 * n + for i in range(howmany): + betterapprox = 0.5 * (approx + n/approx) + approx = betterapprox + prin(betterapprox) .. admonition:: Modify the program ... - All three of the calls to ``newtonSqrt`` in the previous example produce the correct square root for the first parameter. However, were 10 iterations required to get the correct answer? Experiment with different values for the number of repetitions (the 10 on lines 8, 9, and 10). For each of these calls, find the **smallest** value for the number of repetitions that will produce the **correct** result. + The values used in the previous example produce the correct square root for 100. However, were 10 iterations required to get the correct answer? + Experiment with different values for the number of repetitions (howmany on line 2). Find the **smallest** value for the number of + repetitions that will produce the **correct** result. Repeating more than the required number of times is a waste of computing resources. So definite iteration is not a good solution to this problem. @@ -66,15 +66,13 @@ uses a ``while`` condition to execute until the approximation is no longer chang .. codelens:: chp07_newtonswhile - def newtonSqrt(n): - approx = 0.5 * n - better = 0.5 * (approx + n/approx) - while better != approx: - approx = better - better = 0.5 * (approx + n/approx) - return approx - - print(newtonSqrt(10)) + n = 10 + approx = 0.5 * n + better = 0.5 * (approx + n/approx) + while better != approx: + approx = better + better = 0.5 * (approx + n/approx) + print(approx) .. note:: diff --git a/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst b/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst index 67badd49b..8e22d4713 100644 --- a/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst +++ b/_sources/MoreAboutIteration/SentinelValuesAndValidation.rst @@ -60,7 +60,7 @@ zero is a **sentinel value**, a value used to signal the end of the loop. Here's .. activecode:: ch07_sentinel :timelimit: 60000 - + total = 0 count = 0 moreItems = True @@ -119,7 +119,7 @@ When you run the following code, try typing something other than Y or N to see h .. activecode:: ch07_validation :timelimit: 60000 - + valid_input = False response = input('Do you like lima beans? Y)es or N)o: ') while not valid_input: @@ -128,8 +128,8 @@ When you run the following code, try typing something other than Y or N to see h valid_input = True else: response = input('Please enter Y for yes or N for no. \n' + message) - - if response == 'Y': - print('Great! They are very healthy.') - else: - print('Too bad. If cooked right, they are quite tasty.') + + if response == 'Y': + print('Great! They are very healthy.') + else: + print('Too bad. If cooked right, they are quite tasty.') diff --git a/_sources/MoreAboutIteration/The3n1Sequence.rst b/_sources/MoreAboutIteration/The3n1Sequence.rst index 983638731..26ed77599 100644 --- a/_sources/MoreAboutIteration/The3n1Sequence.rst +++ b/_sources/MoreAboutIteration/The3n1Sequence.rst @@ -14,7 +14,7 @@ The 3n + 1 Sequence ------------------- -As another example of indefinite iteration, let's look at a sequence that has fascinated mathematicians for many years. +As another example of iteration with ``while``, let's look at a sequence that has fascinated mathematicians for many years. The rule for creating the sequence is to start from some positive integer, call it ``n``, and to generate the next term of the sequence from ``n``, either by halving ``n``, @@ -70,24 +70,6 @@ You'll notice that if you don't stop when you reach one, the sequence gets into its own loop: 1, 4, 2, 1, 4, 2, 1, 4, and so on. One possibility is that there might be other cycles that we just haven't found. -.. admonition:: Choosing between ``for`` and ``while`` - - Use a ``for`` loop if you know the maximum number of times that you'll - need to execute the body. For example, if you're traversing a list of elements, - or can formulate a suitable call to ``range``, then choose the ``for`` loop. - - So any problem like "iterate this weather model run for 1000 cycles", or "search this - list of words", "check all integers up to 10000 to see which are prime" suggest that a ``for`` loop is best. - - By contrast, if you are required to repeat some computation until some condition is - met, as we did in this 3n + 1 problem, you'll need a ``while`` loop. - - As we noted before, the first case is called **definite iteration** --- we have some definite bounds for - what is needed. The latter case is called **indefinite iteration** --- we are not sure - how many iterations we'll need --- we cannot even establish an upper bound! - - - .. There are also some great visualization tools becoming available to help you .. trace and understand small fragments of Python code. The one we recommend is at .. http://netserv.ict.ru.ac.za/python3_viz diff --git a/_sources/MoreAboutIteration/TheforLoop.rst b/_sources/MoreAboutIteration/TheforLoop.rst index 46e28602b..45366ce09 100644 --- a/_sources/MoreAboutIteration/TheforLoop.rst +++ b/_sources/MoreAboutIteration/TheforLoop.rst @@ -17,11 +17,6 @@ The ``for`` Loop ---------------- -.. youtube:: xGSfiZt5cdw - :divid: forloopvid - :height: 315 - :width: 560 - :align: left The ``while`` statement is a general-purpose tool for iteration, and is necessary for any instance of iteration where we don't know how many repetitions will be needed. However, if we do know how many are needed, there is a more efficient method: the ``for`` statement. @@ -68,6 +63,18 @@ Take a look at the output produced when you press the ``run`` button. There is call **indefinite iteration**. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition controlling the iteration will fail and the iteration will stop. (Unless we have an infinite loop which is of course a problem.) +.. admonition:: Choosing between ``for`` and ``while`` + + Use a ``for`` loop if you know the maximum number of times that you'll + need to execute the body. For example, if you're traversing a list of elements, + or can formulate a suitable call to ``range``, then choose the ``for`` loop. + + So any problem like "iterate this weather model run for 1000 cycles", or "search this + list of words", "check all integers up to 10000 to see which are prime" suggest that a ``for`` loop is best. + + By contrast, if you are required to repeat some computation until some condition is + met, as we did in this 3n + 1 problem, you'll need a ``while`` loop. + What you will notice here is that the ``while`` loop is more work for you --- the programmer --- than the equivalent ``for`` loop. When using a ``while`` loop you have to control the loop variable yourself. You give it an initial value, test @@ -81,7 +88,7 @@ terminates. :answer_a: True :answer_b: False :correct: a - :feedback_a: Although the while loop uses a different syntax, it is just as powerful as a for-loop and often more flexible. + :feedback_a: The syntax for a for-loop can make it easier and more appealing, but a while loop is just as powerful as a for-loop and often more flexible. :feedback_b: Often a for-loop is more natural and convenient for a task, but that same task can always be expressed using a while loop. True or False: You can rewrite any for-loop as a while-loop. diff --git a/_sources/MoreAboutIteration/ThewhileStatement.rst b/_sources/MoreAboutIteration/ThewhileStatement.rst index e0f91cc24..c91b36f28 100644 --- a/_sources/MoreAboutIteration/ThewhileStatement.rst +++ b/_sources/MoreAboutIteration/ThewhileStatement.rst @@ -29,6 +29,7 @@ a boolean expression to control the flow of execution. The body of while (code expression evaluates to ``True``. Here is a simple example that counts down from 10 to 0. + .. activecode:: ch07_while1 count = 10 @@ -38,7 +39,7 @@ Here is a simple example that counts down from 10 to 0. print("Blastoff!") * **count** is a normal variable here, but since it is governing the ``while`` loop it is also called the **loop variable**. -* Line 2 here is the *loop condition**. It must always be a boolean expression that will evaluate to ``False`` or ``True``. +* Line 2 here is the **loop condition**. It must always be a boolean expression that will evaluate to ``False`` or ``True``. * Lines 3 and 4 are the **loop body**. The loop body is always indented. The indentation determines exactly what statements are "in the loop". The loop body is run each time the loop is repeated. @@ -78,7 +79,6 @@ Here is the summation program that uses a while statement. .. activecode:: ch07_while2 """ Return the sum of 1+2+3 ... n """ - aBound = int(input("Please give a number n: ")) theSum = 0 aNumber = 1 @@ -99,15 +99,14 @@ The same program in codelens will allow you to observe the flow of execution. .. codelens:: ch07_while3 - """ Return the sum of 1+2+3 ... n """ - - aBound = int(input("Please give a number n: ")) - theSum = 0 - aNumber = 1 - while aNumber <= aBound: - theSum = theSum + aNumber - aNumber = aNumber + 1 - print(theSum) +""" Return the sum of 1+2+3 ... n """ +aBound = int(input("Please give a number n: ")) +theSum = 0 +aNumber = 1 +while aNumber <= aBound: + theSum = theSum + aNumber + aNumber = aNumber + 1 +print(theSum) diff --git a/_sources/PythonModules/CreatingModules.rst b/_sources/PythonModules/CreatingModules.rst index c704b5971..d425cf397 100644 --- a/_sources/PythonModules/CreatingModules.rst +++ b/_sources/PythonModules/CreatingModules.rst @@ -7,7 +7,7 @@ Creating Modules ---------------- -You've seen how to *use* modules like ``random``, ``math``, and ``turtle``, but how would you *create* a module? +You've seen how to *use* modules like ``random`` and ``math``, but how would you *create* a module? Every time you've written a Python script you've created a module! @@ -120,10 +120,6 @@ Also - look at all the awesome comments in there! It is important to include header comments in your module that explain what the module does. -.. admonition:: Function Comments - - Functions are the next chapter, but the comments used here demonstrate a common Python documentation style. - Ok - so we've got a function in our module now, let's use it. *coffee_customer.py* diff --git a/_sources/PythonModules/MoreAboutUsingModules.rst b/_sources/PythonModules/MoreAboutUsingModules.rst index 4e3076a14..5ea3269ff 100644 --- a/_sources/PythonModules/MoreAboutUsingModules.rst +++ b/_sources/PythonModules/MoreAboutUsingModules.rst @@ -20,18 +20,8 @@ like any other data in Python. Module objects simply contain other Python eleme The first thing we need to do when we wish to use a module is perform an ``import``. In the example above, the statement -``import turtle`` creates a new name, ``turtle``, and makes it refer to a `module object`. This looks very much like +``import math`` creates a new name, ``math``, and makes it refer to a `module object`. This looks very much like the reference diagrams we saw earlier for simple variables. - -.. image:: Figures/modreference.png - -In order to use something contained in a module, we use the `dot` notation, providing the module name and the specific item joined together with a "dot". For example, to use the ``Turtle`` class, we say ``turtle.Turtle``. You should read -this as: "In the module turtle, access the Python element called Turtle". - -We will now turn our attention to a few other modules that you might find useful. - -.. youtube:: SGVgAV0v-Ww - :height: 315 - :width: 560 - :align: left +In order to use something contained in a module, we use the `dot` notation, providing the module name and the specific item joined together with a "dot". For example, to use the ``sqrt`` function, we say ``math.sqrt``. You should read +this as: "In the module math, access the Python element called sqrt". diff --git a/_sources/PythonModules/modules.rst b/_sources/PythonModules/modules.rst index f17176f66..bbd090ff9 100644 --- a/_sources/PythonModules/modules.rst +++ b/_sources/PythonModules/modules.rst @@ -25,28 +25,26 @@ Modules and Getting Help A **module** is a file containing Python definitions and statements intended for use in other Python programs. There are many Python modules that come with -Python as part of the **standard library**. We have already used one of these quite extensively, -the ``turtle`` module. Recall that once we import the module, we can use things +Python as part of the **standard library**. We have already used one of these briefly, +the ``math`` module. Recall that once we import the module, we can use things that are defined inside. .. activecode:: chmod_01 :nocodelens: - import turtle # allows us to use the turtles library + import math # allows us to use the math library - wn = turtle.Screen() # creates a graphics window - alex = turtle.Turtle() # create a turtle named alex + print(math.factorial(10)) # prints 10! + print(math.exp(4)) # prints e^4 - alex.forward(150) # tell alex to move forward by 150 units - alex.left(90) # turn by 90 degrees - alex.forward(75) # complete the second side of a rectangle - wn.exitonclick() + print(math.log2(1024)) # prints log2(1024) + print(math.sqrt(100)) # prints the square root of 100 -Here we are using ``Screen`` and ``Turtle``, both of which are defined inside the turtle module. +Here we are using ``factorial``, ``exp``, ``log2``, and ``sqrt``, all of which are defined inside the math module. -But what if no one had told us about turtle? How would we know +But what if no one had told us about math? How would we know that it exists. How would we know what it can do for us? The answer is to ask for help and the best place to get help about the Python programming environment is to consult with the Python Documentation. @@ -66,13 +64,13 @@ and to use it often. .. image:: Figures/pythondocmedium.png If you have not done so already, take a look at the Global Module Index. Here you will see an alphabetical listing of all -the modules that are available as part of the standard library. Find the turtle module. +the modules that are available as part of the standard library. Find the math module. .. image:: Figures/moduleindexmedium.png -.. image:: Figures/turtlemodmedium.png -You can see that all the turtle functionality that we have talked about is there. However, there is so much more. Take some time to read through and familiarize yourself with some of the other things that turtles can do. +You can see that all the math functionality that we have talked about is there. However, there is so much more. +Take some time to read through and familiarize yourself with some of the other things that math can do. @@ -84,7 +82,7 @@ You can see that all the turtle functionality that we have talked about is there activecode used here was strictly to help us learn. It is not the way we write production programs. To that end, it is necessary to mention that many of the modules available in standard Python - will **not** work in the activecode environment. In fact, only turtle, math, and random have been + will **not** work in the activecode environment. In fact, only math and random have been completely ported at this point. If you wish to explore any additional modules, you will need to also explore using a more robust development environment. diff --git a/_sources/PythonModules/toctree.rst b/_sources/PythonModules/toctree.rst index 246062f60..fc17267f9 100644 --- a/_sources/PythonModules/toctree.rst +++ b/_sources/PythonModules/toctree.rst @@ -7,7 +7,6 @@ Python Modules modules.rst MoreAboutUsingModules.rst - Themathmodule.rst Therandommodule.rst CreatingModules.rst Glossary.rst diff --git a/_sources/Strings/toctree.rst b/_sources/Strings/toctree.rst index 8614a42a8..b926c10ae 100644 --- a/_sources/Strings/toctree.rst +++ b/_sources/Strings/toctree.rst @@ -14,16 +14,15 @@ Strings TheSliceOperator.rst StringsareImmutable.rst StringComparison.rst + Theinandnotinoperators.rst TraversalandtheforLoopByItem.rst TraversalandtheforLoopByIndex.rst TraversalandthewhileLoop.rst - Theinandnotinoperators.rst TheAccumulatorPatternwithStrings.rst - TurtlesandStringsandLSystems.rst + Characterclassification.rst Loopingandcounting.rst Afindfunction.rst Optionalparameters.rst - Characterclassification.rst Summary.rst Glossary.rst Exercises.rst diff --git a/_sources/index.rst b/_sources/index.rst index 0ea5c8280..98fdd802b 100644 --- a/_sources/index.rst +++ b/_sources/index.rst @@ -59,9 +59,8 @@ Table of Contents Selection/toctree.rst Debugging/toctree.rst MoreAboutIteration/toctree.rst - PythonTurtle/toctree.rst - PythonModules/toctree.rst Functions/toctree.rst + PythonModules/toctree.rst Files/toctree.rst Exceptions/toctree.rst IntroRecursion/toctree.rst @@ -72,6 +71,7 @@ Table of Contents Dictionaries/toctree.rst WebApps/toctree.rst GUIandEventDrivenProgramming/toctree.rst + PythonTurtle/toctree.rst Labs :::: diff --git a/cli.log b/cli.log new file mode 100644 index 000000000..02e312d4d --- /dev/null +++ b/cli.log @@ -0,0 +1,7 @@ +INFO : PreTeXt project found in `C:\Users\Rob\Documents\GitHub\thinkcspy`. +WARNING : Project's CLI version could not be detected from `requirements.txt`. +WARNING : Try `pretext init --refresh` to produce a compatible file. +INFO : +CRITICAL: There is not a target named "html" for this project.ptx manifest. +INFO : However, the targets with names ['web', 'runestone', 'subset'] have "html" as their format. Try to view one of those instead or edit your project.ptx manifest. +CRITICAL: Exiting. diff --git a/project-20230129-131712.ptx b/project-20230129-131712.ptx new file mode 100644 index 000000000..686cb6fa1 --- /dev/null +++ b/project-20230129-131712.ptx @@ -0,0 +1,51 @@ + + + + + + + html + source/main.ptx + publication/publication.ptx + output/web + + + pdf + source/main.ptx + publication/publication.ptx + output/print + + + latex + source/main.ptx + publication/publication.ptx + output/print-latex + + + html + source/main.ptx + publication/publication.ptx + output/subset + + + ch_first + + + + latex + pdflatex + xelatex + pdf2svg + asy + sage + convert + pdftops + node + file2brl + + diff --git a/publication/publication.ptx b/publication/publication.ptx new file mode 100644 index 000000000..35f128448 --- /dev/null +++ b/publication/publication.ptx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/requirements-20230129-131712.txt b/requirements-20230129-131712.txt new file mode 100644 index 000000000..51ab65802 --- /dev/null +++ b/requirements-20230129-131712.txt @@ -0,0 +1 @@ +pretextbook == 0.8.3 \ No newline at end of file From 9bbbd27ecd42f3c086e0e86cd0417f2a21870174 Mon Sep 17 00:00:00 2001 From: robotuw Date: Tue, 21 Feb 2023 14:37:49 -0700 Subject: [PATCH 13/90] W10-W13 update First update to the rest of the chapters, weeks 10-13. --- .../ClassesBasics/Achangeofperspective.rst | 19 +++++-------------- .../AddingOtherMethodstoourClass.rst | 4 ++-- _sources/ClassesBasics/ObjectsRevisited.rst | 10 ++++------ .../ObjectsasArgumentsandParameters.rst | 9 ++------- _sources/ClassesBasics/UserDefinedClasses.rst | 2 +- _sources/Files/FindingaFileonyourDisk.rst | 6 +++--- _sources/Files/WithStatements.rst | 3 --- _sources/Files/intro-WorkingwithDataFiles.rst | 4 +++- _sources/IntroRecursion/toctree.rst | 2 -- _sources/index.rst | 2 +- 10 files changed, 21 insertions(+), 40 deletions(-) diff --git a/_sources/ClassesBasics/Achangeofperspective.rst b/_sources/ClassesBasics/Achangeofperspective.rst index f8e3aa12d..1e1b89d14 100644 --- a/_sources/ClassesBasics/Achangeofperspective.rst +++ b/_sources/ClassesBasics/Achangeofperspective.rst @@ -10,21 +10,12 @@ A change of perspective ----------------------- -Throughout the earlier chapters, we wrote functions and called them using a syntax such as ``drawCircle(tess)``. This suggests that the -function is the active agent. It says something like, *"Hey, drawCircle! -Here's a turtle object for you to use to draw with."* +Throughout the earlier chapters, we wrote functions and called them using a syntax such as ``printRange(lst)``. This suggests that the +function is the active agent. It says something like, *"Hey, printRange! +Here's a list for you to use to print with."* -In object-oriented programming, the objects are considered the active agents. -For example, in our early introduction to turtles, we used -an object-oriented style. We said ``tess.forward(100)``, which -asks the turtle to move itself forward by the given number of steps. -An -invocation like ``tess.circle()`` says *"Hey tess! -Please use your circle method!"* - - - -This change in perspective is sometimes considered to be a more "polite" way to write programming instructions. However, it may not initially +In object-oriented programming, the objects are considered the active agents. This change in perspective is sometimes considered to be a more "polite" way +to write programming instructions. However, it may not initially be obvious that it is useful. It turns out that often times shifting responsibility from the functions onto the objects makes it possible to write more versatile functions and makes it easier to maintain and reuse code. diff --git a/_sources/ClassesBasics/AddingOtherMethodstoourClass.rst b/_sources/ClassesBasics/AddingOtherMethodstoourClass.rst index 312dc3e7d..08973b292 100644 --- a/_sources/ClassesBasics/AddingOtherMethodstoourClass.rst +++ b/_sources/ClassesBasics/AddingOtherMethodstoourClass.rst @@ -20,8 +20,8 @@ We can group together the sensible operations, and the kinds of data they apply to, and each instance of the class can have its own state. A **method** behaves like a function but it is invoked on a specific -instance. For example, with a turtle named ``tess``, ``tess.right(90)`` asks the ``tess`` object to perform its -``right`` method and turn 90 degrees. Methods are accessed using dot notation. +instance. For example, with a list named ``lst``, ``lst.append(90)`` asks the ``lst`` object to perform its +``append`` method and add the integer 90 to the end of the list. Methods are accessed using dot notation. Let's add two simple methods to allow a point to give us information about its state. The ``getX`` method, when invoked, will return the value of the x coordinate. The implementation of this method is straight forward since we already know how to write functions that return values. One thing to notice is that even though the ``getX`` method does not need any other parameter information to do its work, there is still one formal parameter, ``self``. As we stated earlier, all methods defined in a class that operate on objects of that class will have ``self`` as their first parameter. Again, this serves as reference to the object itself which in turn gives access to the state data inside the object. diff --git a/_sources/ClassesBasics/ObjectsRevisited.rst b/_sources/ClassesBasics/ObjectsRevisited.rst index e1236bc4f..e0a5f95fb 100644 --- a/_sources/ClassesBasics/ObjectsRevisited.rst +++ b/_sources/ClassesBasics/ObjectsRevisited.rst @@ -12,13 +12,11 @@ Objects Revisited ----------------- -In Python, every value is actually an object. Whether it be a turtle, a list, or even an integer, they are all objects. Programs manipulate those objects either by performing +In Python, every value is actually an object. Whether it be a string, a list, or even an integer, they are all objects. Programs manipulate those objects either by performing computation with them or by asking them to perform methods. To be more specific, we say that an object has a **state** and a collection of **methods** that it can perform. The state of an object represents those things -that the object knows about itself. For example, as we have seen with turtle objects, each turtle has a state consisting -of the turtle's position, its color, its heading and so on. Each turtle also has the ability to go forward, backward, or turn right or left. Individual turtles are different in that even though they are -all turtles, they differ in the specific values of the individual state attributes (maybe they are in a different location or have a different heading). +that the object knows about itself. For example, each list has a state consisting +of the items it contains, a length and so on. Each list also has the ability to add, delete, and sort the items inside of it. Individual lists are different in +that even though they are all lists, they differ in the specific values of the individual state attributes (maybe they have different items inside them). -.. image:: Figures/objectpic1.png - :alt: Simple object has state and methods diff --git a/_sources/ClassesBasics/ObjectsasArgumentsandParameters.rst b/_sources/ClassesBasics/ObjectsasArgumentsandParameters.rst index 6cd2819a4..925c3a070 100644 --- a/_sources/ClassesBasics/ObjectsasArgumentsandParameters.rst +++ b/_sources/ClassesBasics/ObjectsasArgumentsandParameters.rst @@ -10,13 +10,8 @@ Objects as Arguments and Parameters ------------------------------------- -You can pass an object as an argument in the usual way. We've already seen -this in some of the turtle examples where we passed the turtle to -some function like ``drawRectangle`` so that the function could -control and use whatever turtle instance we passed to it. - -Here is a simple function called ``distance`` involving our new ``Point`` objects. The job of this function is to figure out the -distance between two points. +You can pass an object as an argument in the usual way. Here is a simple function called ``distance`` involving our new ``Point`` objects. +The job of this function is to figure out the distance between two points. .. activecode:: chp13_classes6 diff --git a/_sources/ClassesBasics/UserDefinedClasses.rst b/_sources/ClassesBasics/UserDefinedClasses.rst index 6ea76a86b..0dfb99f2c 100644 --- a/_sources/ClassesBasics/UserDefinedClasses.rst +++ b/_sources/ClassesBasics/UserDefinedClasses.rst @@ -14,7 +14,7 @@ User Defined Classes -------------------- -We've already seen classes like ``str``, ``int``, ``float`` and ``Turtle``. These were defined by Python and +We've already seen classes like ``str``, ``int``, and ``float``. These were defined by Python and made available for us to use. However, in many cases when we are solving problems we need to create data objects that are related to the problem we are trying to solve. We need to create our own classes. diff --git a/_sources/Files/FindingaFileonyourDisk.rst b/_sources/Files/FindingaFileonyourDisk.rst index 56d915f14..b043969d0 100755 --- a/_sources/Files/FindingaFileonyourDisk.rst +++ b/_sources/Files/FindingaFileonyourDisk.rst @@ -45,9 +45,9 @@ but the same principles are in use. For example on windows the path might be You can access files in sub-folders, also called directories, under your home directory by adding a slash and the name of the folder. For example, if you had a file -called ``hello.py`` in a folder called ``CS150`` that is inside a folder called -``PyCharmProjects`` under your home directory, then the full name for the file -``hello.py`` is ``/Users/yourname/PyCharmProjects/CS150/hello.py``. +called ``hello.py`` in a folder called ``CS128`` that is inside a folder called +``VSCodeProjects`` under your home directory, then the full name for the file +``hello.py`` is ``/Users/yourname/VSCodeProjects/CS128/hello.py``. This is called an *absolute file path*. An *absolute file path* typically only works on a specific computer. Think about it for a second. What other computer in the world is going to have an *absolute file path* that starts with diff --git a/_sources/Files/WithStatements.rst b/_sources/Files/WithStatements.rst index 4b18ca404..718bc0768 100644 --- a/_sources/Files/WithStatements.rst +++ b/_sources/Files/WithStatements.rst @@ -1,9 +1,6 @@ With Statements --------------- -.. note:: - This section is a bit of an advanced topic and can be easily skipped. But with statements are becoming very common and it doesn't hurt to know about them in case you run into one in the wild. - Now that you have seen and practiced a bit with opening and closing files, there is another mechanism that Python provides for us that cleans up the often forgotten close. Forgetting to close a file does not necessarily cause a runtime error in the kinds of programs you typically write in an introductory CS course. However if you are writing a program that may run for days or weeks at a time that does a lot of file reading and writing you may run into trouble. In version 2.5 Python introduced the concept of a context manager. The context manager automates the process of doing common operations at the start of some task, as well as automating certain operations at the end of some task. In the context of reading and writing a file, the normal operation is to open the file and assign it to a variable. At the end of working with a file the common operation is to make sure that file is closed. diff --git a/_sources/Files/intro-WorkingwithDataFiles.rst b/_sources/Files/intro-WorkingwithDataFiles.rst index fd5abfb27..8a8b7a8e3 100644 --- a/_sources/Files/intro-WorkingwithDataFiles.rst +++ b/_sources/Files/intro-WorkingwithDataFiles.rst @@ -14,7 +14,9 @@ Working with Data Files ======================= -So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life data reside in files. For example the images we worked with in the image processing unit ultimately live in files on your hard drive. Web pages, and word processing documents, and music are other examples of data that live in files. In this short chapter we will introduce the Python concepts necessary to use data from files in our programs. +So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life data reside in files. +For example, web pages, word processing documents, and all data that live in files. In this short chapter we will introduce the Python concepts necessary to use +data from files in our programs. For our purposes, we will assume that our data files are text files--that is, files filled with characters. The Python programs that you write are stored as text files. We can create these files in any of a number of ways. For example, we could use a text editor to type in and save the data. We could also download the data from a website and then save it in a file. Regardless of how the file is created, Python will allow us to manipulate the contents. diff --git a/_sources/IntroRecursion/toctree.rst b/_sources/IntroRecursion/toctree.rst index 0f33af2b5..8da4ecbba 100644 --- a/_sources/IntroRecursion/toctree.rst +++ b/_sources/IntroRecursion/toctree.rst @@ -9,8 +9,6 @@ Recursion CalculatingtheSumofaListofNumbers.rst TheThreeLawsofRecursion.rst ConvertinganIntegertoaStringinAnyBase.rst - intro-VisualizingRecursion.rst - SierpinskiTriangle.rst Glossary.rst ProgrammingExercises.rst Exercises.rst diff --git a/_sources/index.rst b/_sources/index.rst index 98fdd802b..bfd39a59b 100644 --- a/_sources/index.rst +++ b/_sources/index.rst @@ -62,9 +62,9 @@ Table of Contents Functions/toctree.rst PythonModules/toctree.rst Files/toctree.rst - Exceptions/toctree.rst IntroRecursion/toctree.rst ClassesBasics/toctree.rst + Exceptions/toctree.rst ClassesDiggingDeeper/toctree.rst Inheritance/toctree.rst UnitTesting/toctree.rst From 1185f881add6a7b2f6ed2bbac35d22ee0111fdfe Mon Sep 17 00:00:00 2001 From: robotuw Date: Sun, 5 Mar 2023 09:51:35 -0700 Subject: [PATCH 14/90] Fixes Batch Mostly updates based on Ethan's notes. Hopefully this gets the server automatic update working again. --- .../ThePythonProgrammingLanguage.rst | 15 --------------- _sources/GeneralIntro/toctree.rst | 2 +- .../FlowofExecutionofthewhileLoop.rst | 10 +++++----- .../MoreAboutIteration/ThewhileStatement.rst | 17 +++++++++-------- _sources/MoreAboutIteration/toctree.rst | 5 ----- 5 files changed, 15 insertions(+), 34 deletions(-) diff --git a/_sources/GeneralIntro/ThePythonProgrammingLanguage.rst b/_sources/GeneralIntro/ThePythonProgrammingLanguage.rst index c4e689c9d..512b934a4 100644 --- a/_sources/GeneralIntro/ThePythonProgrammingLanguage.rst +++ b/_sources/GeneralIntro/ThePythonProgrammingLanguage.rst @@ -58,11 +58,6 @@ without further translation. .. image:: Figures/compile.png :alt: Compile illustration -Many modern languages use both processes. They are first compiled into a lower -level language, called **byte code**, and then interpreted by a program called -a **virtual machine**. Python uses both processes, but because of the way -programmers interact with it, it is usually considered an interpreted language. - There are two ways to use the Python interpreter: *shell mode* and *program mode*. In shell mode, you type Python expressions into the **Python shell**, and the interpreter immediately shows the result. The example below shows the Python shell at work. @@ -112,16 +107,6 @@ These examples show Python being run from a Unix command line. In other development environments, the details of executing programs may differ. Also, most programs are more interesting than this one. -.. admonition:: Want to learn more about Python? - - If you would like to learn more about installing and using Python, here are some video links. - `Installing Python for Windows `__ shows you how to install the Python environment under - Windows Vista, - `Installing Python for Mac `__ shows you how to install under Mac OS/X, and - `Installing Python for Linux `__ shows you how to install from the Linux - command line. - `Using Python `__ shows you some details about the Python shell and source code. - **Check your understanding** .. mchoice:: question1_2_1 diff --git a/_sources/GeneralIntro/toctree.rst b/_sources/GeneralIntro/toctree.rst index 4a8ddbfbf..0f01d3ef9 100644 --- a/_sources/GeneralIntro/toctree.rst +++ b/_sources/GeneralIntro/toctree.rst @@ -15,9 +15,9 @@ General Introduction RuntimeErrors.rst SemanticErrors.rst ExperimentalDebugging.rst - FormalandNaturalLanguages.rst ATypicalFirstProgram.rst Comments.rst + FormalandNaturalLanguages.rst Glossary.rst Exercises.rst \ No newline at end of file diff --git a/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst index a7b30d4af..1a6f94ae5 100644 --- a/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst +++ b/_sources/MoreAboutIteration/FlowofExecutionofthewhileLoop.rst @@ -34,10 +34,10 @@ the buttons. You can see the value of ``count`` change as the loop iterates thr .. codelens:: vtest -count = 10 -while count > 0: - print(count) - count = count - 1 -print("Blastoff!") + count = 10 + while count > 0: + print(count) + count = count - 1 + print("Blastoff!") diff --git a/_sources/MoreAboutIteration/ThewhileStatement.rst b/_sources/MoreAboutIteration/ThewhileStatement.rst index c91b36f28..7b68775de 100644 --- a/_sources/MoreAboutIteration/ThewhileStatement.rst +++ b/_sources/MoreAboutIteration/ThewhileStatement.rst @@ -38,6 +38,7 @@ Here is a simple example that counts down from 10 to 0. count = count - 1 print("Blastoff!") + * **count** is a normal variable here, but since it is governing the ``while`` loop it is also called the **loop variable**. * Line 2 here is the **loop condition**. It must always be a boolean expression that will evaluate to ``False`` or ``True``. * Lines 3 and 4 are the **loop body**. The loop body is always @@ -99,14 +100,14 @@ The same program in codelens will allow you to observe the flow of execution. .. codelens:: ch07_while3 -""" Return the sum of 1+2+3 ... n """ -aBound = int(input("Please give a number n: ")) -theSum = 0 -aNumber = 1 -while aNumber <= aBound: - theSum = theSum + aNumber - aNumber = aNumber + 1 -print(theSum) + """ Return the sum of 1+2+3 ... n """ + aBound = int(input("Please give a number n: ")) + theSum = 0 + aNumber = 1 + while aNumber <= aBound: + theSum = theSum + aNumber + aNumber = aNumber + 1 + print(theSum) diff --git a/_sources/MoreAboutIteration/toctree.rst b/_sources/MoreAboutIteration/toctree.rst index 6e1842939..1a492e782 100644 --- a/_sources/MoreAboutIteration/toctree.rst +++ b/_sources/MoreAboutIteration/toctree.rst @@ -10,15 +10,10 @@ Iteration FlowofExecutionofthewhileLoop.rst The3n1Sequence.rst SentinelValuesAndValidation.rst - TheforLoop.rst TherangeFunction.rst NewtonsMethod.rst accumulatorRevisited.rst - AlgorithmsRevisited.rst - SimpleTables.rst - 2DimensionalIterationImageProcessing.rst - ImageProcessingonYourOwn.rst Glossary.rst Exercises.rst From 0c107b0fff4b5d5398633961f22fe9ae91867009 Mon Sep 17 00:00:00 2001 From: robotuw Date: Tue, 23 May 2023 15:59:47 -0600 Subject: [PATCH 15/90] Name change Changes made to book and course name for compatibility with Runestone hosting --- pavement.py | 6 +++--- pretext/bookinfo.ptx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pavement.py b/pavement.py index e48cbd584..f7af9f986 100644 --- a/pavement.py +++ b/pavement.py @@ -21,7 +21,7 @@ ######## CHANGE THIS ########## -project_name = "thinkcspy" +project_name = "mines_csstem" ############################### master_url = None @@ -48,7 +48,7 @@ doctrees=doctrees, template_args={ "course_id": project_name, - "course_title": "How\\ to\\ Think\\ like\\ a\\ Computer\\ Scientist", + "course_title": "Computer\\ Science\\ for\\ STEM", "login_required": "false", "appname": master_app, "loglevel": 10, @@ -89,7 +89,7 @@ template_args = { "course_id": project_name, - "course_title": "How\\ to\\ Think\\ like\\ a\\ Computer\\ Scientist", + "course_title": "Computer\\ Science\\ for\\ STEM", "login_required": "false", "appname": master_app, "loglevel": 10, diff --git a/pretext/bookinfo.ptx b/pretext/bookinfo.ptx index 7a12bdd7e..cf275cb34 100644 --- a/pretext/bookinfo.ptx +++ b/pretext/bookinfo.ptx @@ -30,7 +30,7 @@ along with MathBook XML. If not, see . - httlacs + mines_csstem SB From 279e6b3dcfe7a50e739e9c6b0ed674575208c1ba Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Wed, 24 May 2023 09:03:47 -0600 Subject: [PATCH 16/90] Switch to pretext --- pretext/Lists/toctree.ptx | 8 +-- pretext/Selection/Chainedconditionals.ptx | 41 -------------- pretext/Selection/toctree.ptx | 4 +- pretext/Strings/ACollectionDataType.ptx | 12 ++-- pretext/Strings/StringMethods.ptx | 68 ++++++++--------------- pretext/Strings/TheSliceOperator.ptx | 5 +- pretext/Strings/toctree.ptx | 2 +- pretext/thinkcspy.ptx | 14 ++--- 8 files changed, 44 insertions(+), 110 deletions(-) diff --git a/pretext/Lists/toctree.ptx b/pretext/Lists/toctree.ptx index 6586bdd5a..f54a4433f 100644 --- a/pretext/Lists/toctree.ptx +++ b/pretext/Lists/toctree.ptx @@ -5,18 +5,19 @@ 4 4 4 -4 4 4 4 4 +4 +4 +4 +4 4 4 4 4 -4 4 -4 4 4 4 @@ -25,7 +26,6 @@ 4 4 4 -4 4 4 4 diff --git a/pretext/Selection/Chainedconditionals.ptx b/pretext/Selection/Chainedconditionals.ptx index 835b296d8..c992f9998 100644 --- a/pretext/Selection/Chainedconditionals.ptx +++ b/pretext/Selection/Chainedconditionals.ptx @@ -146,45 +146,4 @@ else: - - -

What will the following code print if x = 3, y = 5, and z = 2?

- - -if x < y and x < z: - print("a") -elif y < x and y < z: - print("b") -else: - print("c") - - - - - - -

a

-
- - While the value in x is less than the value in y (3 is less than 5) it is not less than the value in z (3 is not less than 2). - -
- - -

b

-
- - The value in y is not less than the value in x (5 is not less than 3). - -
- - -

c

-
- - Since the first two Boolean expressions are false the else will be executed. - -
-
-
diff --git a/pretext/Selection/toctree.ptx b/pretext/Selection/toctree.ptx index 981367449..d1fc3942a 100644 --- a/pretext/Selection/toctree.ptx +++ b/pretext/Selection/toctree.ptx @@ -2,12 +2,12 @@ 4Selection 4 -4 -4 4 4 4 4 +4 +4 4 4 4 diff --git a/pretext/Strings/ACollectionDataType.ptx b/pretext/Strings/ACollectionDataType.ptx index 28d162cb1..c64156c3d 100644 --- a/pretext/Strings/ACollectionDataType.ptx +++ b/pretext/Strings/ACollectionDataType.ptx @@ -1,12 +1,11 @@
A Collection Data Type -

So far we have seen built-in types like: int, float, - bool, str and we've seen lists. - int, float, and - bool are considered to be simple or primitive data types because their values are not composed + +

So far we have seen built-in types like: int, float, and str.

+

int and float are considered to be simple or primitive data types because their values are not composed of any smaller parts. They cannot be broken down. - On the other hand, strings and lists are different from the others because they + On the other hand, strings (and lists that we will talk about next chapter) are different from the others because they are made up of smaller pieces. In the case of strings, they are made up of smaller strings each containing one character.

Types that are comprised of smaller pieces are called collection data types. @@ -14,5 +13,6 @@ single entity (the whole), or we may want to access its parts. This ambiguity is useful.

Strings can be defined as sequential collections of characters. This means that the individual characters that make up the string are assumed to be in a particular order from left to right.

-

A string that contains no characters, often referred to as the empty string, is still considered to be a string. It is simply a sequence of zero characters and is represented by ‘' or (two single or two double quotes with nothing in between).

+

A string that contains no characters, often referred to as the empty string, is still considered to be a string.

+

It is simply a sequence of zero characters and is represented by ‘' or (two single or two double quotes with nothing in between).

diff --git a/pretext/Strings/StringMethods.ptx b/pretext/Strings/StringMethods.ptx index 6fa2be71d..8ee74a412 100644 --- a/pretext/Strings/StringMethods.ptx +++ b/pretext/Strings/StringMethods.ptx @@ -2,12 +2,10 @@
String Methods -

We previously saw that each turtle instance has its own attributes and - a number of methods that can be applied to the instance. For example, - we wrote tess.right(90) when we wanted the turtle object tess to perform the right method to turn - to the right 90 degrees. The dot notation is the way we connect the name of an object to the name of a method - it can perform.

-

Strings are also objects. Each string instance has its own attributes and methods. The most important attribute of the string is the collection of characters. There are a wide variety of methods. Try the following program.

+

We previously used a few functions like print() and input(). A method is a function that is attached to a specific Python object. + To access this function, we write the object, then a dot ., and then the name of the method. The "dot notation" is the way we connect the name of an object to the name of a method + it can perform. For example, we can write ss.upper() when we wanted the string ss to perform the upper() method to create an upper-case version of itself.

+

Remember that Strings are objects. Each string instance has its own attributes and methods. The most important attribute of the string is the collection of characters. There are a wide variety of methods. Try the following program.

ss = "Hello, World" @@ -338,7 +336,7 @@ print(s[1] * s.index("n"))
- String Format Method + F-Strings

In grade school quizzes a common convention is to use fill-in-the blanks. For instance,

Hello _____!

@@ -346,24 +344,23 @@ print(s[1] * s.index("n"))

and you can fill in the name of the person greeted, and combine given text with a chosen insertion. We use this as an analogy: Python has a similar - construction, better called fill-in-the-braces. The string method format, makes + construction, called a formatted string or an f-string. An f-string makes substitutions into places in a string enclosed in braces. Run this code:

person = input('Your name: ') -greeting = 'Hello {}!'.format(person) +greeting = f'Hello {person}!' print(greeting)

There are several new ideas here!

-

The string for the format method has a special form, with braces embedded. - Such a string is called a format string. Places where - braces are embedded are replaced by the value of an expression - taken from the parameter list for the format method. There are many +

The string has been formatted in a new way. We have included an f before the starting quotation mark. + Such a string is called an f-string. Places where + braces are embedded are replaced by the value of the expression inside the braces. There are many variations on the syntax between the braces. In this case we use the syntax where the first (and only) location in the string with - braces has a substitution made from the first (and only) parameter.

+ braces has the variable person. When this code is evaluated, the value of the person variable is placed in the string in this location.

In the code above, this new string is assigned to the identifier greeting, and then the string is printed.

The identifier @@ -374,7 +371,7 @@ print(greeting) person = input('Enter your name: ') -print('Hello {}!'.format(person)) +print(f'Hello {person}!')

There can be multiple substitutions, with data of any type. @@ -384,32 +381,28 @@ print('Hello {}!'.format(person)) origPrice = float(input('Enter the original price: $')) discount = float(input('Enter discount percentage: ')) newPrice = (1 - discount/100)*origPrice -calculation = '${} discounted by {}% is ${}.'.format(origPrice, discount, newPrice) +calculation = f'${origPrice} discounted by {discount}% is ${newPrice}.' print(calculation) -

The parameters are inserted into the braces in order.

If you used the data suggested, this result is not satisfying. Prices should appear with exactly two places beyond the decimal point, but that is not the default way to display floats.

-

Format strings can give further information inside the braces +

F-strings can give further information inside the braces showing how to specially format data. In particular floats can be shown with a specific number of decimal places. - For two decimal places, put :.2f inside the braces for the monetary values:

+ For two decimal places, put :.2f inside the braces but after the variable name for the monetary values:

origPrice = float(input('Enter the original price: $')) discount = float(input('Enter discount percentage: ')) newPrice = (1 - discount/100)*origPrice -calculation = '${:.2f} discounted by {}% is ${:.2f}.'.format(origPrice, discount, newPrice) +calculation = f'${origPrice:.2f} discounted by {discount}% is ${newPrice:.2f}.' print(calculation)

The 2 in the format modifier can be replaced by another integer to round to that specified number of digits.

-

This kind of format string depends directly on the order of the - parameters to the format method. There are other approaches that we will - skip here, explicitly numbering substitutions and taking substitutions from a dictionary.

A technical point: Since braces have special meaning in a format string, there must be a special rule if you want braces to actually be included in the final formatted string. The rule is to double @@ -419,25 +412,10 @@ print(calculation) formatted string:

a = 5
 b = 9
-setStr =  'The set is {​{ {},{} }​}.'.format(a, b)
+setStr = f'The set is {​{ {a},{b} }​}.'
 print(setStr)

Unfortunately, at the time of this writing, the ActiveCode format implementation has a bug, printing doubled braces, but standard Python prints {5, 9}.

-

You can have multiple placeholders indexing the same argument, or perhaps even have extra - arguments that are not referenced at all:

- - -letter = """ -Dear {0} {2}. - {0}, I have an interesting money-making proposition for you! - If you deposit $10 million into my bank account, I can - double your money ... -""" - -print(letter.format("Paris", "Whitney", "Hilton")) -print(letter.format("Bill", "Henry", "Gates")) - -

What is printed by the following statements?

@@ -445,7 +423,7 @@ print(letter.format("Bill", "Henry", "Gates")) x = 2 y = 6 -print('sum of {} and {} is {}; product: {}.'.format( x, y, x+y, x*y)) +print(f'sum of {x} and {y} is {x+y}; product: {x*y}.')
@@ -455,15 +433,15 @@ print('sum of {} and {} is {}; product: {}.'.format( x, y, x+y, x*y))

Nothing - it causes an error

- It is legal format syntax: put the data in place of the braces. + It is legal format syntax. -

sum of {} and {} is {}; product: {}. 2 6 8 12

+

sum of {} and {} is {}; product: {}.

- Put the data into the format string; not after it. + Put the value of each expression in place of the braces.
@@ -471,7 +449,7 @@ print('sum of {} and {} is {}; product: {}.'.format( x, y, x+y, x*y))

sum of 2 and 6 is 8; product: 12.

- Yes, correct substitutions! + Yes, correct!
@@ -490,7 +468,7 @@ print('sum of {} and {} is {}; product: {}.'.format( x, y, x+y, x*y)) v = 2.34567 -print('{:.1f} {:.2f} {:.7f}'.format(v, v, v)) +print(f'{v:.1f} {v:.2f} {v:.7f}') diff --git a/pretext/Strings/TheSliceOperator.ptx b/pretext/Strings/TheSliceOperator.ptx index 9a038c491..8e846d375 100644 --- a/pretext/Strings/TheSliceOperator.ptx +++ b/pretext/Strings/TheSliceOperator.ptx @@ -13,10 +13,7 @@ print(singers[17:21])

The slice operator [n:m] returns the part of the string from the n'th character to the m'th character, including the first but excluding the last. In other words, start with the character at index n and - go up to but do not include the character at index m. - This - behavior may seem counter-intuitive but if you recall the range function, it did not include its end - point either.

+ go up to but do not include the character at index m.

If you omit the first index (before the colon), the slice starts at the beginning of the string. If you omit the second index, the slice goes to the end of the string.

diff --git a/pretext/Strings/toctree.ptx b/pretext/Strings/toctree.ptx index 8ce6ed93a..d4b8c7668 100644 --- a/pretext/Strings/toctree.ptx +++ b/pretext/Strings/toctree.ptx @@ -8,8 +8,8 @@ 4 4 4 -4 4 +4 4 4 4 diff --git a/pretext/thinkcspy.ptx b/pretext/thinkcspy.ptx index 2baf5ad71..1856dc116 100644 --- a/pretext/thinkcspy.ptx +++ b/pretext/thinkcspy.ptx @@ -13,24 +13,24 @@ + + + + - - - - - - - + + + From 60dcbb55db7d1781dd2f3754e615a02b34d92b60 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Wed, 24 May 2023 09:40:17 -0600 Subject: [PATCH 17/90] Apply classes/files/recursion changes to ptx --- pretext/ClassesBasics/Achangeofperspective.ptx | 16 +++++----------- .../AddingOtherMethodstoourClass.ptx | 4 ++-- pretext/ClassesBasics/ObjectsRevisited.ptx | 12 ++++++------ .../ObjectsasArgumentsandParameters.ptx | 8 ++------ pretext/ClassesBasics/UserDefinedClasses.ptx | 2 +- pretext/Files/FindingaFileonyourDisk.ptx | 6 +++--- pretext/Files/WithStatements.ptx | 3 --- pretext/Files/intro-WorkingwithDataFiles.ptx | 3 ++- pretext/IntroRecursion/toctree.ptx | 2 -- pretext/MoreAboutIteration/toctree.ptx | 7 +++---- 10 files changed, 24 insertions(+), 39 deletions(-) diff --git a/pretext/ClassesBasics/Achangeofperspective.ptx b/pretext/ClassesBasics/Achangeofperspective.ptx index 71c3bec0d..d928a8e9e 100644 --- a/pretext/ClassesBasics/Achangeofperspective.ptx +++ b/pretext/ClassesBasics/Achangeofperspective.ptx @@ -1,17 +1,11 @@
A change of perspective -

Throughout the earlier chapters, we wrote functions and called them using a syntax such as drawCircle(tess). This suggests that the - function is the active agent. It says something like, Hey, drawCircle! - Here's a turtle object for you to use to draw with.

-

In object-oriented programming, the objects are considered the active agents. - For example, in our early introduction to turtles, we used - an object-oriented style. We said tess.forward(100), which - asks the turtle to move itself forward by the given number of steps. - An - invocation like tess.circle() says Hey tess! - Please use your circle method!

-

This change in perspective is sometimes considered to be a more polite way to write programming instructions. However, it may not initially +

Throughout the earlier chapters, we wrote functions and called them using a syntax such as printRange(lst). This suggests that the + function is the active agent. It says something like, "Hey, printRange! + Here's a list for you to use to print with."

+

In object-oriented programming, the objects are considered the active agents. This change in perspective is sometimes considered to be a more "polite" way + to write programming instructions. However, it may not initially be obvious that it is useful. It turns out that often times shifting responsibility from the functions onto the objects makes it possible to write more versatile functions and makes it easier to maintain and reuse code.

diff --git a/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx b/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx index 8365cd680..5efd49969 100644 --- a/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx +++ b/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx @@ -10,8 +10,8 @@ We can group together the sensible operations, and the kinds of data they apply to, and each instance of the class can have its own state.

A method behaves like a function but it is invoked on a specific - instance. For example, with a turtle named tess, tess.right(90) asks the tess object to perform its - right method and turn 90 degrees. Methods are accessed using dot notation.

+ instance. For example, with a list named lst, lst.append(90) asks the lst object to perform its + append method and add the integer 90 to the end of the list. Methods are accessed using dot notation.

Let's add two simple methods to allow a point to give us information about its state. The getX method, when invoked, will return the value of the x coordinate. The implementation of this method is straight forward since we already know how to write functions that return values. One thing to notice is that even though the getX method does not need any other parameter information to do its work, there is still one formal parameter, self. As we stated earlier, all methods defined in a class that operate on objects of that class will have self as their first parameter. Again, this serves as reference to the object itself which in turn gives access to the state data inside the object.

diff --git a/pretext/ClassesBasics/ObjectsRevisited.ptx b/pretext/ClassesBasics/ObjectsRevisited.ptx index ea2f44fcf..a15cb0817 100644 --- a/pretext/ClassesBasics/ObjectsRevisited.ptx +++ b/pretext/ClassesBasics/ObjectsRevisited.ptx @@ -1,11 +1,11 @@
Objects Revisited -

In Python, every value is actually an object. Whether it be a turtle, a list, or even an integer, they are all objects. Programs manipulate those objects either by performing - computation with them or by asking them to perform methods. To be more specific, we say that an object has - a state and a collection of methods that it can perform. The state of an object represents those things - that the object knows about itself. For example, as we have seen with turtle objects, each turtle has a state consisting - of the turtle's position, its color, its heading and so on. Each turtle also has the ability to go forward, backward, or turn right or left. Individual turtles are different in that even though they are - all turtles, they differ in the specific values of the individual state attributes (maybe they are in a different location or have a different heading).

+

In Python, every value is actually an object. Whether it be a string, a list, or even an integer, they are all objects. Programs manipulate those objects either by performing + computation with them or by asking them to perform methods. To be more specific, we say that an object has + a state and a collection of methods that it can perform. The state of an object represents those things + that the object knows about itself. For example, each list has a state consisting + of the items it contains, a length and so on. Each list also has the ability to add, delete, and sort the items inside of it. Individual lists are different in + that even though they are all lists, they differ in the specific values of the individual state attributes (maybe they have different items inside them).

Simple object has state and methods
diff --git a/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx b/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx index 93a00188f..58067f71f 100644 --- a/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx +++ b/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx @@ -1,12 +1,8 @@
Objects as Arguments and Parameters -

You can pass an object as an argument in the usual way. We've already seen - this in some of the turtle examples where we passed the turtle to - some function like drawRectangle so that the function could - control and use whatever turtle instance we passed to it.

-

Here is a simple function called distance involving our new Point objects. The job of this function is to figure out the - distance between two points.

+

You can pass an object as an argument in the usual way. Here is a simple function called distance involving our new Point objects. + The job of this function is to figure out the distance between two points.

import math diff --git a/pretext/ClassesBasics/UserDefinedClasses.ptx b/pretext/ClassesBasics/UserDefinedClasses.ptx index 7a7a52a72..f0cf67485 100644 --- a/pretext/ClassesBasics/UserDefinedClasses.ptx +++ b/pretext/ClassesBasics/UserDefinedClasses.ptx @@ -1,7 +1,7 @@
User Defined Classes -

We've already seen classes like str, int, float and Turtle. These were defined by Python and +

We've already seen classes like str, int, and float. These were defined by Python and made available for us to use. However, in many cases when we are solving problems we need to create data objects that are related to the problem we are trying to solve. We need to create our own classes.

As an example, consider the concept of a mathematical point. In two dimensions, a point is two diff --git a/pretext/Files/FindingaFileonyourDisk.ptx b/pretext/Files/FindingaFileonyourDisk.ptx index 0f4e8a364..e0bc90208 100644 --- a/pretext/Files/FindingaFileonyourDisk.ptx +++ b/pretext/Files/FindingaFileonyourDisk.ptx @@ -30,9 +30,9 @@

You can access files in sub-folders, also called directories, under your home directory by adding a slash and the name of the folder. For example, if you had a file - called hello.py in a folder called CS150 that is inside a folder called - PyCharmProjects under your home directory, then the full name for the file - hello.py is /Users/yourname/PyCharmProjects/CS150/hello.py. + called hello.py in a folder called CS128 that is inside a folder called + VSCodeProjects under your home directory, then the full name for the file + hello.py is /Users/yourname/VSCodeProjects/CS128/hello.py. This is called an absolute file path. An absolute file path typically only works on a specific computer. Think about it for a second. What other computer in the world is going to have an absolute file path that starts with diff --git a/pretext/Files/WithStatements.ptx b/pretext/Files/WithStatements.ptx index d356755b3..0bee04a3e 100644 --- a/pretext/Files/WithStatements.ptx +++ b/pretext/Files/WithStatements.ptx @@ -1,9 +1,6 @@

With Statements - -

This section is a bit of an advanced topic and can be easily skipped. But with statements are becoming very common and it doesn't hurt to know about them in case you run into one in the wild.

-

Now that you have seen and practiced a bit with opening and closing files, there is another mechanism that Python provides for us that cleans up the often forgotten close. Forgetting to close a file does not necessarily cause a runtime error in the kinds of programs you typically write in an introductory CS course. However if you are writing a program that may run for days or weeks at a time that does a lot of file reading and writing you may run into trouble.

In version 2.5 Python introduced the concept of a context manager. The context manager automates the process of doing common operations at the start of some task, as well as automating certain operations at the end of some task. In the context of reading and writing a file, the normal operation is to open the file and assign it to a variable. At the end of working with a file the common operation is to make sure that file is closed.

The Python with statement makes using context managers easy. The general form of a with statement is:

diff --git a/pretext/Files/intro-WorkingwithDataFiles.ptx b/pretext/Files/intro-WorkingwithDataFiles.ptx index 2d7c753bb..ab952e8a3 100644 --- a/pretext/Files/intro-WorkingwithDataFiles.ptx +++ b/pretext/Files/intro-WorkingwithDataFiles.ptx @@ -1,7 +1,8 @@
Working with Data Files -

So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life data reside in files. For example the images we worked with in the image processing unit ultimately live in files on your hard drive. Web pages, and word processing documents, and music are other examples of data that live in files. In this short chapter we will introduce the Python concepts necessary to use data from files in our programs.

+

So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life data reside in files.

+

For example, web pages, word processing documents, and all data that live in files. In this short chapter we will introduce the Python concepts necessary to use data from files in our programs.

For our purposes, we will assume that our data files are text files–that is, files filled with characters. The Python programs that you write are stored as text files. We can create these files in any of a number of ways. For example, we could use a text editor to type in and save the data. We could also download the data from a website and then save it in a file. Regardless of how the file is created, Python will allow us to manipulate the contents.

In Python, we must open files before we can use them and close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

diff --git a/pretext/IntroRecursion/toctree.ptx b/pretext/IntroRecursion/toctree.ptx index ead8eaa13..d16ca3cb8 100644 --- a/pretext/IntroRecursion/toctree.ptx +++ b/pretext/IntroRecursion/toctree.ptx @@ -5,8 +5,6 @@ 4 4 4 -4 -4 4 4 4 diff --git a/pretext/MoreAboutIteration/toctree.ptx b/pretext/MoreAboutIteration/toctree.ptx index 46986a334..f7b6b7a76 100644 --- a/pretext/MoreAboutIteration/toctree.ptx +++ b/pretext/MoreAboutIteration/toctree.ptx @@ -1,14 +1,13 @@ -4More About Iteration +4Iteration 4 -4 4 -4 +4 4 +4 4 4 -4 4 4 4 From 6cb1be741f711099bfa68a28742de059074cf346 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Wed, 24 May 2023 11:15:20 -0600 Subject: [PATCH 18/90] Add new loops sections --- .../ThePythonProgrammingLanguage.ptx | 14 -- pretext/GeneralIntro/toctree.ptx | 2 +- .../FlowofExecutionofthewhileLoop.ptx | 20 +++ pretext/MoreAboutIteration/TheforLoop.ptx | 86 ++++++++++ .../TherangeFunction.ptx | 22 +-- .../MoreAboutIteration/ThewhileStatement.ptx | 158 +++++++++--------- pretext/MoreAboutIteration/toctree.ptx | 7 +- 7 files changed, 197 insertions(+), 112 deletions(-) create mode 100644 pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx create mode 100644 pretext/MoreAboutIteration/TheforLoop.ptx rename pretext/{PythonTurtle => MoreAboutIteration}/TherangeFunction.ptx (95%) diff --git a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx index 237728fcb..7063970cc 100644 --- a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx +++ b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx @@ -34,10 +34,6 @@ executable. Once a program is compiled, you can execute it repeatedly without further translation.

-

Many modern languages use both processes. They are first compiled into a lower - level language, called byte code, and then interpreted by a program called - a virtual machine. Python uses both processes, but because of the way - programmers interact with it, it is usually considered an interpreted language.

There are two ways to use the Python interpreter: shell mode and program mode. In shell mode, you type Python expressions into the Python shell, and the interpreter immediately shows the result. The example below shows the Python shell at work.

@@ -75,16 +71,6 @@ My first program adds two numbers, 2 and 3:

These examples show Python being run from a Unix command line. In other development environments, the details of executing programs may differ. Also, most programs are more interesting than this one.

- - Want to learn more about Python? -

If you would like to learn more about installing and using Python, here are some video links. - Installing Python for Windows shows you how to install the Python environment under - Windows Vista, - Installing Python for Mac shows you how to install under Mac OS/X, and - Installing Python for Linux shows you how to install from the Linux - command line. - Using Python shows you some details about the Python shell and source code.

-

Check your understanding

diff --git a/pretext/GeneralIntro/toctree.ptx b/pretext/GeneralIntro/toctree.ptx index bf79d640a..0c51b26fd 100644 --- a/pretext/GeneralIntro/toctree.ptx +++ b/pretext/GeneralIntro/toctree.ptx @@ -11,9 +11,9 @@ 4 4 4 -4 4 4 +4 4 4
diff --git a/pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx b/pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx new file mode 100644 index 000000000..943ea9f8b --- /dev/null +++ b/pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx @@ -0,0 +1,20 @@ + +
+ Flow of Execution of the while Loop +

As before with ``if``, loops allow us as programmers to manipulate the control flow of a Python program. + We can now possibly skip a portion of code, or choose to repeat it an indefinite number of times.

+

The flowchart below provides the general sequence of steps that govern execution of a while loop.

+ +

A codelens demonstration is a good way to help you visualize exactly how the flow of control + works with the while loop. Try stepping forward and backward through the program by pressing + the buttons. You can see the value of count change as the loop iterates through the values from 10 to 0.

+ + + count = 10 + while count > 0: + print(count) + count = count - 1 + print("Blastoff!") + + +
diff --git a/pretext/MoreAboutIteration/TheforLoop.ptx b/pretext/MoreAboutIteration/TheforLoop.ptx new file mode 100644 index 000000000..d98fc4484 --- /dev/null +++ b/pretext/MoreAboutIteration/TheforLoop.ptx @@ -0,0 +1,86 @@ + +
+ The <c>for</c> loop +

The while statement is a general-purpose tool for iteration, and is necessary for any instance of iteration where we don't know how many repetitions will be needed. +However, if we do know how many are needed, there is a more efficient method: the for statement.

+

As a simple example, let's say we have some friends, and +we'd like to send them each an email inviting them to our party. We +don't quite know how to send email yet, so for the moment we'll just print a +message for each friend.

+ + + for name in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: + print(f"Hi {name}! Please come to my party on Saturday!") + + +

Take a look at the output produced when you press the run button. There is one line printed for each friend. Here's how it works:

+
    +
  • name in this for statement is the loop variable.
  • +
  • The list of names in the square brackets is a regular list. Later we'll see that other types besides lists can be put in this spot.
  • +
  • Line 2 is the loop body. Like with while, the loop body is always indented. The loop body is performed one time for each name in the list.
  • +
  • On each iteration or pass of the loop, a check is done to see if + there are still more items to be processed. If there are none left (this is + called the terminating condition of the loop), the loop has finished. + Program execution continues at the next statement after the loop body.
  • +
  • If there are items still to be processed, the loop variable is updated to + refer to the next item in the list. This means, in this case, that the loop + body is executed here 7 times, and each time name will refer to a different + friend.
  • +
  • At the end of each execution of the body of the loop, Python returns + to the for statement, to see if there are more items to be handled.
  • +
+ + +

Introduction of the for statement causes us to think about the types of iteration we have seen. The for statement will always iterate through a sequence of + values like the list of names for the party.

+

Since we know that it will iterate once for each value in the collection, it is often said that a for loop creates a + definite iteration because we definitely know how many times we are going to iterate. On the other + hand, the while statement is dependent on a condition that needs to evaluate to False in order + for the loop to terminate. Since we do not necessarily know when this will happen, it creates what we + call indefinite iteration. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition + controlling the iteration will fail and the iteration will stop. (Unless we have an infinite loop which is of course a problem.)

+
+ + + Choosing between <c>for</c> and <c>while</c> +

Use a for loop if you know the maximum number of times that you'll + need to execute the body. For example, if you're traversing a list of elements, + or can formulate a suitable call to range, then choose the for loop.

+

So any problem like "iterate this weather model run for 1000 cycles", or "search this + list of words", "check all integers up to 10000 to see which are prime" suggest that a for loop is best.

+

By contrast, if you are required to repeat some computation until some condition is + met, as we did in this 3n + 1 problem, you'll need a while loop.

+
+ +

What you will notice here is that the while loop is more work for +you --- the programmer --- than the equivalent for loop. When using a while +loop you have to control the loop variable yourself. You give it an initial value, test +for completion, and then make sure you change something in the body so that the loop +terminates.

+ + <b>Check your understanding</b> + + + +

True or False: You can rewrite any for-loop as a while-loop.

+
+ + + +

True

+
+ + The syntax for a for-loop can make it easier and more appealing, but a while loop is just as powerful as a for-loop and often more flexible. + +
+ + +

False

+
+ + Often a for-loop is more natural and convenient for a task, but that same task can always be expressed using a while loop. + +
+
+
+
diff --git a/pretext/PythonTurtle/TherangeFunction.ptx b/pretext/MoreAboutIteration/TherangeFunction.ptx similarity index 95% rename from pretext/PythonTurtle/TherangeFunction.ptx rename to pretext/MoreAboutIteration/TherangeFunction.ptx index 1c79cedd4..05f9fdbaa 100644 --- a/pretext/PythonTurtle/TherangeFunction.ptx +++ b/pretext/MoreAboutIteration/TherangeFunction.ptx @@ -2,21 +2,8 @@
The range Function
diff --git a/pretext/MoreAboutIteration/NewtonsMethod.ptx b/pretext/MoreAboutIteration/NewtonsMethod.ptx index e4c677c9c..755a5b205 100644 --- a/pretext/MoreAboutIteration/NewtonsMethod.ptx +++ b/pretext/MoreAboutIteration/NewtonsMethod.ptx @@ -21,21 +21,21 @@ better = 1/2 * (approx + n/approx) calculation yielding a better result.

-def newtonSqrt(n, howmany): - approx = 0.5 * n - for i in range(howmany): - betterapprox = 0.5 * (approx + n/approx) - approx = betterapprox - return betterapprox + n = 100 + howmany = 10 -print(newtonSqrt(100, 10)) -print(newtonSqrt(4, 10)) -print(newtonSqrt(1, 10)) + approx = 0.5 * n + for i in range(howmany): + betterapprox = 0.5 * (approx + n/approx) + approx = betterapprox + prin(betterapprox) Modify the program … -

All three of the calls to newtonSqrt in the previous example produce the correct square root for the first parameter. However, were 10 iterations required to get the correct answer? Experiment with different values for the number of repetitions (the 10 on lines 8, 9, and 10). For each of these calls, find the smallest value for the number of repetitions that will produce the correct result.

+

The values used in the previous example produce the correct square root for 100. However, were 10 iterations required to get the correct answer? + Experiment with different values for the number of repetitions (howmany on line 2). Find the smallest value for the number of + repetitions that will produce the correct result.

Repeating more than the required number of times is a waste of computing resources. So definite iteration is not a good solution to this problem.

In general, Newton's algorithm will eventually reach a point where the new approximation is no better than the previous. At that point, we could simply stop. @@ -45,15 +45,13 @@ print(newtonSqrt(1, 10)) uses a while condition to execute until the approximation is no longer changing. Each time through the loop we compute a better approximation using the formula described earlier. As long as the better is different, we try again. Step through the program and watch the approximations get closer and closer.

- def newtonSqrt(n): - approx = 0.5 * n - better = 0.5 * (approx + n/approx) - while better != approx: - approx = better - better = 0.5 * (approx + n/approx) - return approx - - print(newtonSqrt(10)) +n = 10 +approx = 0.5 * n +better = 0.5 * (approx + n/approx) +while better != approx: + approx = better + better = 0.5 * (approx + n/approx) +print(approx) diff --git a/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx b/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx index 8c7cca24d..fb2201e90 100644 --- a/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx +++ b/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx @@ -3,7 +3,7 @@ Other uses of <c>while</c> Sentinel Values -

Indefinite loops are much more common in the real world than definite loops.

+

The indefinite loops provided by the ``while`` statement are common in the real world.

  • @@ -55,24 +55,21 @@ zero is a sentinel value, a value used to signal the end of the loop. Here's the code:

    -def checkout(): - total = 0 - count = 0 - moreItems = True - while moreItems: - price = float(input('Enter price of item (0 when done): ')) - if price != 0: + total = 0 + count = 0 + moreItems = True + while moreItems: + price = float(input('Enter price of item (0 when done): ')) + if price != 0: count = count + 1 total = total + price print('Subtotal: $', total) - else: + else: moreItems = False - average = total / count - print('Total items:', count) - print('Total $', total) - print('Average price per item: $', average) - -checkout() + average = total / count + print('Total items:', count) + print('Total $', total) + print('Average price per item: $', average)

    There are still a few problems with this program.

    @@ -133,23 +130,19 @@ checkout() When you run the following code, try typing something other than Y or N to see how the code reacts:

    -def get_yes_or_no(message): - valid_input = False - answer = input(message) - while not valid_input: - answer = answer.upper() # convert to upper case - if answer == 'Y' or answer == 'N': + valid_input = False + response = input('Do you like lima beans? Y)es or N)o: ') + while not valid_input: + response = response.upper() # convert to upper case + if response == 'Y' or response == 'N': valid_input = True + else: + response = input('Please enter Y for yes or N for no. \n' + message) + if response == 'Y': + print('Great! They are very healthy.') else: - answer = input('Please enter Y for yes or N for no. \n' + message) - return answer - -response = get_yes_or_no('Do you like lima beans? Y)es or N)o: ') -if response == 'Y': - print('Great! They are very healthy.') -else: - print('Too bad. If cooked right, they are quite tasty.') - + print('Too bad. If cooked right, they are quite tasty.') + diff --git a/pretext/MoreAboutIteration/The3n1Sequence.ptx b/pretext/MoreAboutIteration/The3n1Sequence.ptx index 1b7602f41..2c8cdcaa4 100644 --- a/pretext/MoreAboutIteration/The3n1Sequence.ptx +++ b/pretext/MoreAboutIteration/The3n1Sequence.ptx @@ -1,27 +1,26 @@
    The 3n + 1 Sequence -

    As another example of indefinite iteration, let's look at a sequence that has fascinated mathematicians for many years. +

    As another example of iteration with while, let's look at a sequence that has fascinated mathematicians for many years. The rule for creating the sequence is to start from some positive integer, call it n, and to generate the next term of the sequence from n, either by halving n, whenever n is even, or else by multiplying it by three and adding 1 when it is odd. The sequence terminates when n reaches 1.

    -

    This Python function captures that algorithm. Try running this program several times supplying different values for n.

    +

    This Python code captures that algorithm. Try running this program several times supplying different values for n.

    -def seq3np1(n): - """ Print the 3n+1 sequence from n, terminating when it reaches 1.""" - while n != 1: + n = 3 + + """ Print the 3n+1 sequence from n, terminating when it reaches 1.""" + while n != 1: print(n) if n % 2 == 0: # n is even - n = n // 2 + n = n // 2 else: # n is odd - n = n * 3 + 1 - print(n) # the last print is 1 - -seq3np1(3) - + n = n * 3 + 1 + print(n) # the last print is 1 +

    The condition for this loop is n != 1. The loop will continue running until n == 1 (which will make the condition false).

    @@ -36,16 +35,7 @@ seq3np1(3) time through the loop until it reaches 1.

    You might like to have some fun and see if you can find a small starting number that needs more than a hundred steps before it terminates.

    - - Lab -

    -

      -
    • -

      Experimenting with the 3n+1 Sequence In this guided lab exercise we will try to learn more about this sequence.

      -
    • -
    -

    -
    +

    Particular values aside, the interesting question is whether we can prove that this sequence terminates for all positive values of n. So far, no one has been able to prove it or disprove it!

    diff --git a/pretext/MoreAboutIteration/intro-IterationRevisited.ptx b/pretext/MoreAboutIteration/intro-IterationRevisited.ptx index daecea209..f463e292a 100644 --- a/pretext/MoreAboutIteration/intro-IterationRevisited.ptx +++ b/pretext/MoreAboutIteration/intro-IterationRevisited.ptx @@ -6,8 +6,6 @@ people do poorly.

    Repeated execution of a sequence of statements is called iteration. Because iteration is so common, Python provides several language features to make it - easier. We've already seen the for statement in a previous chapter. This is a very common - form of iteration in Python. In this chapter - we are going to look at the while statement — another way to have your - program do iteration.

    + easier. easier. In this chapter we are going to look at two common forms of iteration: the while statement + and the for` statement.

    diff --git a/pretext/PythonModules/CreatingModules.ptx b/pretext/PythonModules/CreatingModules.ptx index a62e7566a..d2843d3b0 100644 --- a/pretext/PythonModules/CreatingModules.ptx +++ b/pretext/PythonModules/CreatingModules.ptx @@ -1,7 +1,7 @@
    Creating Modules -

    You've seen how to use modules like random, math, and turtle, but how would you create a module?

    +

    You've seen how to use modules like random and math, but how would you create a module?

    Every time you've written a Python script you've created a module!

    A Python module is just a Python source code file. Let's consider the Python file shown below.

    @@ -154,10 +154,6 @@ def order_coffee(size, roast): Module Comments

    It is important to include header comments in your module that explain what the module does.

    - - Function Comments -

    Functions are the next chapter, but the comments used here demonstrate a common Python documentation style.

    -

    Ok - so we've got a function in our module now, let's use it.

    coffee_customer.py diff --git a/pretext/PythonModules/MoreAboutUsingModules.ptx b/pretext/PythonModules/MoreAboutUsingModules.ptx index 2ca17a267..b8a719511 100644 --- a/pretext/PythonModules/MoreAboutUsingModules.ptx +++ b/pretext/PythonModules/MoreAboutUsingModules.ptx @@ -1,15 +1,16 @@

    More About Using Modules +

    Before we move on to exploring other modules, we should say a bit more about what modules are and how we - typically use them. One of the most important things to realize about modules is the fact that they are data objects, just - like any other data in Python. Module objects simply contain other Python elements.

    + typically use them. One of the most important things to realize about modules is the fact that they are data objects, just + like any other data in Python. Module objects simply contain other Python elements.

    +

    The first thing we need to do when we wish to use a module is perform an import. In the example above, the statement - import turtle creates a new name, turtle, and makes it refer to a module object. This looks very much like - the reference diagrams we saw earlier for simple variables.

    - -

    In order to use something contained in a module, we use the dot notation, providing the module name and the specific item joined together with a dot. For example, to use the Turtle class, we say turtle.Turtle. You should read - this as: In the module turtle, access the Python element called Turtle.

    -

    We will now turn our attention to a few other modules that you might find useful.

    -
    diff --git a/pretext/PythonModules/modules.ptx b/pretext/PythonModules/modules.ptx index a18b44559..60b994877 100644 --- a/pretext/PythonModules/modules.ptx +++ b/pretext/PythonModules/modules.ptx @@ -4,24 +4,22 @@
    From f34b57f31a4a689823b126c986e0c99192204f03 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 8 Jun 2023 09:39:27 -0600 Subject: [PATCH 25/90] Elaborate on list slice step --- pretext/Lists/ListSlices.ptx | 2 ++ pretext/MoreAboutIteration/intro-IterationRevisited.ptx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pretext/Lists/ListSlices.ptx b/pretext/Lists/ListSlices.ptx index b3c7f97ef..ff81dcdf8 100644 --- a/pretext/Lists/ListSlices.ptx +++ b/pretext/Lists/ListSlices.ptx @@ -58,6 +58,8 @@ print(alist[4:])

    Slice also takes a third value, the step size. + This specifies the rate at which we increment (if the step size is positive) + or the rate at which we decrement (if the step size is negative). We can also specify -1 as the step term to slice with the values in reverse.

    diff --git a/pretext/MoreAboutIteration/intro-IterationRevisited.ptx b/pretext/MoreAboutIteration/intro-IterationRevisited.ptx index f463e292a..ea9399dc3 100644 --- a/pretext/MoreAboutIteration/intro-IterationRevisited.ptx +++ b/pretext/MoreAboutIteration/intro-IterationRevisited.ptx @@ -7,5 +7,5 @@

    Repeated execution of a sequence of statements is called iteration. Because iteration is so common, Python provides several language features to make it easier. easier. In this chapter we are going to look at two common forms of iteration: the while statement - and the for` statement.

    + and the for statement.

    From f7f3b141f38e7f109186b41fb0c12b9d5e5a9adb Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 8 Jun 2023 09:59:12 -0600 Subject: [PATCH 26/90] Write break/continue section --- .../MoreAboutIteration/BreakAndContinue.ptx | 36 +++++++++++++++++++ pretext/MoreAboutIteration/toctree.ptx | 1 + 2 files changed, 37 insertions(+) create mode 100644 pretext/MoreAboutIteration/BreakAndContinue.ptx diff --git a/pretext/MoreAboutIteration/BreakAndContinue.ptx b/pretext/MoreAboutIteration/BreakAndContinue.ptx new file mode 100644 index 000000000..1c0420543 --- /dev/null +++ b/pretext/MoreAboutIteration/BreakAndContinue.ptx @@ -0,0 +1,36 @@ + +
    + <c>break</c> and <c>continue</c> + +

    In loops, we sometimes want to traverse until we reach a certain value. + We could make some sort of loop condition with a boolean that is toggled as True once we + reach that value, but there's an easier way: the break statement.

    + +

    When a break statement is reached, the loop immediately ends and proceeds with the code after the loop. + break is only a valid statement inside of loops, such as the following:

    + + + +for i in range(0, 10): + if i == 5: + break + print(i) + + + +

    The continue statement is another keyword that we can use in loops. + When a continue statement is reached, the current iteration is stopped (similar to break), + however, the loop will continue running for all iterations after the current one.

    + + + +for i in range(0, 10): + if i == 5: + continue + print(i) + + + + Notice the difference between the activecode example above for break and this example with continue. + Neither loop reaches 5, but in the loop with continue, it continues iterating after where 5 would have been. +
    diff --git a/pretext/MoreAboutIteration/toctree.ptx b/pretext/MoreAboutIteration/toctree.ptx index 9dd8c2d2d..5cf14a161 100644 --- a/pretext/MoreAboutIteration/toctree.ptx +++ b/pretext/MoreAboutIteration/toctree.ptx @@ -11,6 +11,7 @@ 4 4 4 +4 4 4 From 0e5daa57e38dfd674da2a85f8d4dec9c0091bb8b Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 8 Jun 2023 10:01:02 -0600 Subject: [PATCH 27/90] Fix toctree for iteration chapter --- pretext/MoreAboutIteration/toctree.ptx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretext/MoreAboutIteration/toctree.ptx b/pretext/MoreAboutIteration/toctree.ptx index 5cf14a161..0501fedff 100644 --- a/pretext/MoreAboutIteration/toctree.ptx +++ b/pretext/MoreAboutIteration/toctree.ptx @@ -11,7 +11,7 @@ 4 4 4 -4 +4 4 4 From 1aa39f5c3e6794adbd9c8f17a476786259ab264c Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 8 Jun 2023 10:53:47 -0600 Subject: [PATCH 28/90] Update build files --- README.rst | 14 -------------- pretext/GenFigs/play-button/play-button.png | Bin 0 -> 6621 bytes pretext/GenFigs/qrcode/GoogleLogic.png | Bin 0 -> 580 bytes pretext/GenFigs/qrcode/HriDtn-0Dcw.png | Bin 0 -> 596 bytes pretext/GenFigs/qrcode/advrange.png | Bin 0 -> 569 bytes pretext/GenFigs/qrcode/assignvid.png | Bin 0 -> 574 bytes pretext/GenFigs/qrcode/booleanexpressions.png | Bin 0 -> 564 bytes pretext/GenFigs/qrcode/codelensvid.png | Bin 0 -> 596 bytes pretext/GenFigs/qrcode/expression_vid.png | Bin 0 -> 554 bytes pretext/GenFigs/qrcode/forloopvid.png | Bin 0 -> 550 bytes .../qrcode/function_accumulator_pattern.png | Bin 0 -> 562 bytes pretext/GenFigs/qrcode/function_intro.png | Bin 0 -> 557 bytes pretext/GenFigs/qrcode/inputvid.png | Bin 0 -> 578 bytes pretext/GenFigs/qrcode/precedencevid.png | Bin 0 -> 570 bytes pretext/GenFigs/qrcode/reassignmentvid.png | Bin 0 -> 567 bytes pretext/GenFigs/qrcode/typesnconvert.png | Bin 0 -> 599 bytes pretext/GenFigs/qrcode/unaryselection.png | Bin 0 -> 583 bytes pretext/GenFigs/qrcode/updatevid.png | Bin 0 -> 601 bytes pretext/GenFigs/qrcode/vid_modules.png | Bin 0 -> 547 bytes pretext/GenFigs/qrcode/vid_turtleintro.png | Bin 0 -> 596 bytes pretext/GenFigs/qrcode/whileloop.png | Bin 0 -> 545 bytes pretext/GenFigs/trace/ch07_while3.js | 4 ++++ pretext/GenFigs/trace/chp07_newtonswhile.js | 2 +- requirements.txt | 2 +- 24 files changed, 6 insertions(+), 16 deletions(-) create mode 100644 pretext/GenFigs/play-button/play-button.png create mode 100644 pretext/GenFigs/qrcode/GoogleLogic.png create mode 100644 pretext/GenFigs/qrcode/HriDtn-0Dcw.png create mode 100644 pretext/GenFigs/qrcode/advrange.png create mode 100644 pretext/GenFigs/qrcode/assignvid.png create mode 100644 pretext/GenFigs/qrcode/booleanexpressions.png create mode 100644 pretext/GenFigs/qrcode/codelensvid.png create mode 100644 pretext/GenFigs/qrcode/expression_vid.png create mode 100644 pretext/GenFigs/qrcode/forloopvid.png create mode 100644 pretext/GenFigs/qrcode/function_accumulator_pattern.png create mode 100644 pretext/GenFigs/qrcode/function_intro.png create mode 100644 pretext/GenFigs/qrcode/inputvid.png create mode 100644 pretext/GenFigs/qrcode/precedencevid.png create mode 100644 pretext/GenFigs/qrcode/reassignmentvid.png create mode 100644 pretext/GenFigs/qrcode/typesnconvert.png create mode 100644 pretext/GenFigs/qrcode/unaryselection.png create mode 100644 pretext/GenFigs/qrcode/updatevid.png create mode 100644 pretext/GenFigs/qrcode/vid_modules.png create mode 100644 pretext/GenFigs/qrcode/vid_turtleintro.png create mode 100644 pretext/GenFigs/qrcode/whileloop.png create mode 100644 pretext/GenFigs/trace/ch07_while3.js diff --git a/README.rst b/README.rst index b1dce3d73..c63c49ea5 100644 --- a/README.rst +++ b/README.rst @@ -43,17 +43,3 @@ Building for Production on a Runestone Server 1. clone this repo to `httlacs` instead of `thinkcspy` 2. Run `rsmanage addcourse` and add `httlacs` as course name and base course name 3. Run `rsmanage build --ptx httlacs` - - -Building with runestone ------------------------ -As mentioned above this method is deprecated, but will still work. -Any updates to this book should be made in PreTeXt NOT RST. - -You can build it and host it yourself in just a few simple steps: - - 1. ``pip install -r requirements.txt`` -- Should install everything you need - 2. ``runestone build`` -- will build the html and put it in ``./build/thinkcspy`` - 3. ``runestone serve`` -- will start a webserver and serve the pages locally from ``./build/thinkcspy`` - - diff --git a/pretext/GenFigs/play-button/play-button.png b/pretext/GenFigs/play-button/play-button.png new file mode 100644 index 0000000000000000000000000000000000000000..9e26551e125a2b03f6e8004afcecc5fe6d3d90ed GIT binary patch literal 6621 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 SA}3%(r=ww@{z>)8>;D0-9!YWl literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/GoogleLogic.png b/pretext/GenFigs/qrcode/GoogleLogic.png new file mode 100644 index 0000000000000000000000000000000000000000..7f70825006fc908f67257481581e6d19c150ef57 GIT binary patch literal 580 zcmV-K0=xZ*P)X2M5QRSmq+Vhv2biNcH^`CZYUU`p0baI5^k%`2-O6TWVKt;-(ZcR;@r27&#lujB zl{P?|Pe{>9iuFH!@h@Xi|3|?psVueW8OxW6V21Fb+v~1AG|(j4|$6 zx?YJgeF0($>x1v||V^fr9uMeP@IxX|hoO2z8+9-XFT8}xsv}-A6%ETtvT@w3(!h(VQ zE#K=`{n*s$JB8ZcQ~aD(dizyBHdQkEQE++eF?09dtNNcq1#^@1>GGE$xzpeFo6P$N z>c^uV;yxai#ZUw0*~wMZIp630Ue(FpXy=H%svnzb!?rT3c4%8a5u9;<3H29m$F}?E SNui_w0000?X{GCj#ESvbJ7Yk_d{7Nw%}{ap=s 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 literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/forloopvid.png b/pretext/GenFigs/qrcode/forloopvid.png new file mode 100644 index 0000000000000000000000000000000000000000..f954d70fc1db081e4a7b2d4b8b1ec2475189b09e GIT binary patch literal 550 zcmV+>0@?kEP)q%zrx0QszpNyk-xdTKGVJHR}GrZhgt?tq!Oy>$Kel-rz# z4+lYD`|G+QWi|rgS?_?>|9D+$>-Uq7X!6P~AG+VSrPdnKWPdyCsOt(8S_`~X$MOv! zNz+l)pPK@FB>BtarEK-SXUz5#)#aD$d{iz8&QZ|1iyO(TU}T;f1l>A}~bTOV>rH#X< z`+Xy7`<((_Fpm!m1{wb01jr7n{@m1N?!_{u4@JasL-4}F`?!m)D^Q#76mr_s8aXLD o%!gHfZfdPRe4^lc#%xM`0Sw@~?wnzjIRF3v07*qoM6N<$f=dAuZ~y=R literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/function_accumulator_pattern.png b/pretext/GenFigs/qrcode/function_accumulator_pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..a911066cbab7cce0e25220b0e7d0ecfd290c1f47 GIT binary patch literal 562 zcmV-20?qx2P)1K$ENmVV_x&l$_%-2-gRo^{TL}Uhdet_l@keNwk21F!WrR&>M z;V@6X0uUGUDOc;d0~Ow$B`sSZEgvZ5LS1*Dj`cprm0IAFs**;%KbP9aRD=EH=R#d~ zplYI9dPh~jvpwx^a;xh5rhvFo>r0MSX&?@dc|L{as9x&*L{~* zTT`3aCfus}z9}DZJvg5F2wsPpRo^#7ZQIm(&*bfd>M?C6ZdZNZ6lNto(S6O0=2g1x zK%w~+aaHv`CXl?L)~@=#Dc@n;+S`#<&HGsLx2nExiuZ$T(qm)69B8ZR`=)BJE$?eT z$E`ilH{22XQz&Z0GrOmWuVdBln5R;_E~)@8|LM)-x2nE>Y7?1DsL2l{pr4OF0wn-! z(zg13sbe4WW$5eH>%Gm9_vcW-ZwIGUDVr#4K`EO+`MF-E>mHPKae(JzMdlLf%$v)j z=A1=YPvLM;@4Drf8Jm#s?Um$C{+wOa}RsaA107*qoM6N<$g2*Ki A9{>OV literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/function_intro.png b/pretext/GenFigs/qrcode/function_intro.png new file mode 100644 index 0000000000000000000000000000000000000000..003dc64acaa38c8fbc272d06bea29579afc2bcfb GIT binary patch literal 557 zcmV+|0@D47P)NklI^zdTZP}j*Q_46+?`_vn*cyh`^5HNuOX!zq~gqsOKTj@FjRlkJfH#R$^q^m?M-tNLS8Ku|ICIos8T2%X}*2JBV+u_@FC<+dv2c-if@)O8l> zVK8|Z%mb5|`pE++`CD&Qi$YS&o0RgS%PHTDPU!*cR{gOlAmk~|>H#os^0B?DKQ=`g z<>aBx>?{|fxs|RnP^`RsGV~#m@;;S%T&wq$C=Vebh+e~2^nwQ(u08^wv=Z-C{jn+5 zRt%I|VWMsNw5wFn!7hH{agZzKI$xK=z8nZG*S>tQ6OQo+NJrro`z7ECK*3-Ht?Y{u| zd9>VDp-S$3T-ynGN_L;-Ikl+bDmdlA=WRCKXntRh>KJdrf)*2iK^I}ZM!-eeOV>M4 z9n6MCbFwg95iCX;{L{pIjdob|r>9a?AJG8VeeOs_{;wYFzMrmdPo;j2g@+;h)4<1a zZ9%A_P)U$x5QV=Qd+(NVfEtT9WlL_oEc_E^Rx=9^FxU&!f=}wFq9{L?4S6^L zpgBlPtCO^rXZ+$%#-RR=f=QCJI!TH!tximelzY-~)t{S!X(dHmbBJgLQpBg#iS$7n zRsFds-~65)9wve9uj`7G-64Gon*Yr|UYBa?{TyN`H>wlvsQ2BdI$SRB?PW(@SD;d& z=kyK|gh`&#qpF=JB>0V4PAkVr-Rex>@&14(jb#+`ks1APhlTjSD?HA zYV<8oz;d8oB zklG1~+11z1PFm&;f8URygt&Hbnq}4Sm|dwf@|M+)qTibQqpCkQk2@59LeByQq}o8^zymZ*ezW*P!yg6~N}PJHYZ@nmW_^ zvLmZMIklPDow8L+=^V3|8Ov=qUH?7Ro>N$EF0$M{F>o@%rx&2nQ|L}<4o|a>heujT z7rSpZYECDrIj2yX#xci!rtYj9RsFfCI$U!yr0k~*kJ**_0=J#F;iWNJ-2eap07*qo IM6N<$f(kqrTmS$7 literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/reassignmentvid.png b/pretext/GenFigs/qrcode/reassignmentvid.png new file mode 100644 index 0000000000000000000000000000000000000000..2f8e5fdc69fb301e9f792885d3f9ff93567d4108 GIT binary patch literal 567 zcmV-70?7S|P)WX%od-8tKkzMsb%#ir*<=20OB+VxEaw#Yyr${e3h=xqV^Hu z1k6fkZARDoQ$E=921L848C`EnQT%=oFi0zdw1$MVb-%Al9W{t~`*wJtu1}!GySIq_ zW`cy`gbB*M*sA(-Q$SF*8#kUHK}b&d#I2y7$HJ3mrV# z-!I!$e{#weZsvXuH}hZP??kp6hVJ*3s8Q?}LHIJ_bVT}nbk~>9N2}^jPT3L?_yjP> zYyt>ZBTo4-=zd>^dWtilbav)@zVA7w8uhTRmP#Ib9yi=p)t{RpcPc~r9yCiIv#eiLrL@+{yH)r5TGZ2btB@XBn8&*B z8M6+RKhVx4Sw8gdy}I95qsIHGq76xLF<`&Q2w&x^R;%jYhw>-DGv?LYhoV{UDb%Av zHh5bATlW0-5L@<<+;M1F{fVigh9{RVZ&~>rtaWH`P}2@~$aO3X)PNw4b9!e{QNN zdNuSxk~SxzO3O!_{(czMb~kR+8VB~e@4eNm`!Q5km4~r;)V-$W45jL3OWU4>I@u|E zhwEnD527G`5_qSk@*6b^Q||{-ZFCSf*WR_Y{ zI&AdkrmDxRqMvYrP-t#bW!C*js<&045A0LW7k|IGsrQ4ZHph(bz7W&hh*yKw;TA74 zXwDRdP<8LM{<)df%LgI@XY8XmoeI$-;bvD l<+`Eo&axk4&3Vo!>MwH}jXwBvj^qFU002ovPDHLkV1gAWC9D7d literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/unaryselection.png b/pretext/GenFigs/qrcode/unaryselection.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7676aed570ee0ae573cc5b0cf88628597afa08 GIT binary patch literal 583 zcmV-N0=WH&P)1E44^vo);zT4nR!UouK?G8dl#qb(q;5V6zFWe3(`~3;;8m zUZv|RQTAg8wmGQGcq6(#E%iLdAsMmqKMv|bMU`##=M4F3jS>Ko(yMfRdg>e@yPKz< z7wY;7)THxL+xO(x@!bUeY-?40-xQaevl4W$+tLpovN{r``-A(do-_Nzss`|dE9QP%yQvyBv%aV-3 z$T_tryB{~fVOH)O6Kpdj@#H>3v+BF1fLKZ>An2OqfznuLRej$SKJBNciI1`>sC3m@ zRo^$|ksW>7FWaoU&5?8JP**R%;?DA13nS-Lq>860)vTAaxraP@X?3Z|?M+BYDG*bR+HOi3LVKrxtaN$2RL_?iy2mFyg)r^#}Bm Voe$Nv(F_0p002ovPDHLkV1lK(9kT!c literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/updatevid.png b/pretext/GenFigs/qrcode/updatevid.png new file mode 100644 index 0000000000000000000000000000000000000000..9baf6df6de9b3aae6897c7904b1540c58c0934f3 GIT binary patch literal 601 zcmV-f0;c_mP)zaa5>&0bfUSk;_a{=GRRC~E zy!!(AS|p}x5!mEqy1oPDb^odB=R*_+gGdIIP)B{pt;wcM?us= zD{-DBerW~J^!qcZ?9nBAU4D%iXFUnmQDfPv^HTVGlTaRX;klUN#}#KNPYEu!%0&V=F)|uhRAY6o*^d znCdqBjMiSJ>pM`sMf9#HJfzvpLm*!Zgx_9ghI|rL@2voEs=q{}W@(|kQrG)ahr9B2 zIS$W=VV-NhhN?9tKunw11gxJk$NUm1dumZ>msgvp-sjosEb8z-1z^8DOtdIxW(p@# ntL$aGx%}3O9o(!j&!qkUI1H5YPH5nz00000NkvXXu0mjfYTzSw literal 0 HcmV?d00001 diff --git a/pretext/GenFigs/qrcode/vid_modules.png b/pretext/GenFigs/qrcode/vid_modules.png new file mode 100644 index 0000000000000000000000000000000000000000..2d14ef8b05e195ba1294f40e36d91f0cea234ea5 GIT binary patch literal 547 zcmV+;0^I$HP)%QhPWtEMI;O)O806Rk46n ztiHNFomKtCDYNHZ&fsMB1PBou*^JrDY&@;{OH)+Yo^t%%WgV&O7L<)4VrCC9n+L+n zG_4*8G3~@BR)1-#%6kY>UTh$3xP*9!t~*f0Zc;tD8&8lRC|~P)Z4)X*TI`(Yste7d zblriXv{j|A9hUu3B=>RM?;BCxz#-VY4cfdw!0ICag3ZpW{@N7emKIWZN!W+@A=3T6 zA(f&Y;4Gi(`(EcXqxKaC_S32~P}6(EJ*)a_Q>nhs!%V4+?n7O7o>%>~sjpGGtXM9D z-q*IGs&OT$o}_*k`b?oAwMQ}iVF3okGE?aFeKV>)w;HNpCRN_|8nX>m68)XyX_V9b z{zs{FS~am5tPkbhYB^ljEvWnkfTr-WX2M7)0MUAoUVUbATL$zH)A0AEgh_l3BK7t7ZW>o~&jTC^&(Ih1+jY0=g)EpcE&~ zL6TM{%>Z$&-}uG9ltKL;1yQBNA#C|4NfL2&%C&CQU!F>4b_X;kkE9J?Hvr7cf0eFp zPx+6k5uP5>ZyA6{U#RPcQPSfkv$tYAcJD;jccy~!yO%~t%#$o#Xs=qenbyNjqniafEP`@p`s=qc>O3Ct0pZHdJo=JkX&8o1AV+FAUFVMR^EM(_&8N zwN-ec?EL9AJf{&=9X)U5lxdc@e*7VZ-?yU9exJQPY!Fv>>VV-nZ72_6#RxCUwfOKy z(g%y$P2H-$HuZUo=hvJzwT*G#lBy+a6ysUpobOjR{Js%&G%-0(=2OSF828O6 zCzdw}k|&RQl9jWQdw5yj>aR<2vUV(5?E5Q&x(H z`0!{BFJqZ@gXDpcbDB}7dkUw~o^wvFjdg89s@_v5N43d}WpZLMvoh;;tp383|Mae9 za+{G1!S1z8U!&_MP=B?3GKkuZ_&xz?BHtDnXNIk)dQYLG&2-D@#_sjZuxs@frjAnY i1Rlw`%v^a(`f#k+9~9T^w@NT|oj46iy<)VgzJ&JQ%Ryh?yiK9053z zTfT=c{ACR4ztl{g^L&UbA%WywpbJ2~kXYr$W^`SaLaz6@!$vqVh6HjO^}Z@~4oA$}uge>CeF6m*V*~UO zpKrug)%Q(73%nV6Gxw68>iec_%;ok!pR(Sl>mw+g>{Ud}%i|Dro3{B!udPKv zjg8uwK<%))<>$>=^=Vdp-;}jfTYv<;#9&KdKU-DbHwEjp;bHQD!f3ur*C$Xq&&9NB zkqOL>2X55+N|d+HkU-$@1VF*=699nPdRtY04Qdw=nH)tXfHB-fQ#Ami-dCcm=EPtf zmN7fa9IXwXQ;Sk#quGr;V5RIk9}Txv^?g$o;P4DH)!!F6=GgbOC>5MbMDh&X0 zpslL!n=0Z;SdeW01@)LCQ>aLZ", "globals": {}, "ordered_globals": [], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 2, "event": "step_line", "func_name": "", "globals": {}, "ordered_globals": [], "stack_to_render": [], "heap": {}, "stdout": ""}, {"event": "raw_input", "prompt": "Please give a number n: "}]} \ No newline at end of file diff --git a/pretext/GenFigs/trace/chp07_newtonswhile.js b/pretext/GenFigs/trace/chp07_newtonswhile.js index 6ca51d2ef..c785dd710 100644 --- a/pretext/GenFigs/trace/chp07_newtonswhile.js +++ b/pretext/GenFigs/trace/chp07_newtonswhile.js @@ -1,4 +1,4 @@ if (allTraceData === undefined) { var allTraceData = {}; } - allTraceData["chp07_newtonswhile"] = {"code": "def newtonSqrt(n):\n approx = 0.5 * n\n better = 0.5 * (approx + n/approx)\n while better != approx:\n approx = better\n better = 0.5 * (approx + n/approx)\n return approx\n\nprint(newtonSqrt(10))\n\n", "trace": [{"line": 1, "event": "step_line", "func_name": "", "globals": {}, "ordered_globals": [], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 9, "event": "step_line", "func_name": "", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 1, "event": "call", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10}, "ordered_varnames": ["n"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 2, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10}, "ordered_varnames": ["n"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 3, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"]}, "ordered_varnames": ["n", "approx"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"], "better": 3.5}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"], "better": 3.5}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.5, "better": 3.5}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.5, "better": 3.1786}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.5, "better": 3.1786}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1786, "better": 3.1786}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1786, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1786, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 7, "event": "step_line", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_varnames": ["n", "approx", "better"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 7, "event": "return", "func_name": "newtonSqrt", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [{"func_name": "newtonSqrt", "is_parent": false, "frame_id": 1, "parent_frame_id_list": [], "encoded_locals": {"n": 10, "approx": 3.1623, "better": 3.1623, "__return__": 3.1623}, "ordered_varnames": ["n", "approx", "better", "__return__"], "is_zombie": false, "is_highlighted": true, "unique_hash": "newtonSqrt_f1"}], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": ""}, {"line": 9, "event": "return", "func_name": "", "globals": {"newtonSqrt": ["REF", 1]}, "ordered_globals": ["newtonSqrt"], "stack_to_render": [], "heap": {"1": ["FUNCTION", "newtonSqrt(n)", null]}, "stdout": "3.162277660168379\n"}]} \ No newline at end of file + allTraceData["chp07_newtonswhile"] = {"code": "n = 10\napprox = 0.5 * n\nbetter = 0.5 * (approx + n/approx)\nwhile better != approx:\n approx = better\n better = 0.5 * (approx + n/approx)\nprint(approx)\n\n", "trace": [{"line": 1, "event": "step_line", "func_name": "", "globals": {}, "ordered_globals": [], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 2, "event": "step_line", "func_name": "", "globals": {"n": 10}, "ordered_globals": ["n"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 3, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"]}, "ordered_globals": ["n", "approx"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"], "better": 3.5}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": ["SPECIAL_FLOAT", "5.0"], "better": 3.5}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.5, "better": 3.5}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.5, "better": 3.1786}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.5, "better": 3.1786}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1786, "better": 3.1786}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1786, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1786, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 5, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 6, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 4, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 7, "event": "step_line", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": ""}, {"line": 7, "event": "return", "func_name": "", "globals": {"n": 10, "approx": 3.1623, "better": 3.1623}, "ordered_globals": ["n", "approx", "better"], "stack_to_render": [], "heap": {}, "stdout": "3.162277660168379\n"}]} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 20a98cf59..30f82a1cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pretextbook >= 0.8.0 +pretext == 1.6.0 \ No newline at end of file From dd29d5550a24b7e7683e39bccf284b6bab85c8d2 Mon Sep 17 00:00:00 2001 From: robotuw Date: Mon, 12 Jun 2023 11:48:11 -0600 Subject: [PATCH 29/90] Chapter 1 Update Updated text content for chapter 1 as well as activity names for future grading. --- pretext/GeneralIntro/ExperimentalDebugging.ptx | 2 +- pretext/GeneralIntro/FormalandNaturalLanguages.ptx | 4 ++-- pretext/GeneralIntro/MoreAboutPrograms.ptx | 2 +- pretext/GeneralIntro/RuntimeErrors.ptx | 4 ++-- pretext/GeneralIntro/SemanticErrors.ptx | 4 ++-- .../GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx | 4 ++-- pretext/GeneralIntro/Syntaxerrors.ptx | 4 ++-- pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx | 6 +++--- pretext/GeneralIntro/WhatisDebugging.ptx | 2 +- pretext/GeneralIntro/intro-TheWayoftheProgram.ptx | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pretext/GeneralIntro/ExperimentalDebugging.ptx b/pretext/GeneralIntro/ExperimentalDebugging.ptx index 7ad0526b7..771a5519c 100644 --- a/pretext/GeneralIntro/ExperimentalDebugging.ptx +++ b/pretext/GeneralIntro/ExperimentalDebugging.ptx @@ -28,7 +28,7 @@

    Check your understanding

    - +

    The difference between programming and debugging is:

    diff --git a/pretext/GeneralIntro/FormalandNaturalLanguages.ptx b/pretext/GeneralIntro/FormalandNaturalLanguages.ptx index 66e4e3d88..e6cb1eb25 100644 --- a/pretext/GeneralIntro/FormalandNaturalLanguages.ptx +++ b/pretext/GeneralIntro/FormalandNaturalLanguages.ptx @@ -100,7 +100,7 @@

    Check your understanding

    - +

    The differences between natural and formal languages include:

    @@ -139,7 +139,7 @@
    - +

    True or False: Reading a program is like reading other kinds of text.

    diff --git a/pretext/GeneralIntro/MoreAboutPrograms.ptx b/pretext/GeneralIntro/MoreAboutPrograms.ptx index bfcecddda..4ba5be1e9 100644 --- a/pretext/GeneralIntro/MoreAboutPrograms.ptx +++ b/pretext/GeneralIntro/MoreAboutPrograms.ptx @@ -43,7 +43,7 @@

    Check your understanding

    - +

    A program is:

    diff --git a/pretext/GeneralIntro/RuntimeErrors.ptx b/pretext/GeneralIntro/RuntimeErrors.ptx index d489fc253..71b4d6b61 100644 --- a/pretext/GeneralIntro/RuntimeErrors.ptx +++ b/pretext/GeneralIntro/RuntimeErrors.ptx @@ -10,7 +10,7 @@

    Check your understanding

    - +

    Which of the following is a run-time error?

    @@ -41,7 +41,7 @@
    - +

    Who or what typically finds runtime errors?

    diff --git a/pretext/GeneralIntro/SemanticErrors.ptx b/pretext/GeneralIntro/SemanticErrors.ptx index 748edfe1c..d303e2468 100644 --- a/pretext/GeneralIntro/SemanticErrors.ptx +++ b/pretext/GeneralIntro/SemanticErrors.ptx @@ -12,7 +12,7 @@

    Check your understanding

    - +

    Which of the following is a semantic error?

    @@ -43,7 +43,7 @@
    - +

    Who or what typically finds semantic errors?

    diff --git a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx index 501724dda..0c8dd18a6 100644 --- a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx +++ b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx @@ -65,7 +65,7 @@ print(2 + 3)

    Check your understanding

    - +

    The activecode interpreter allows you to (select all that apply):

    @@ -104,7 +104,7 @@ print(2 + 3)
    - +

    Codelens allows you to (select all that apply):

    diff --git a/pretext/GeneralIntro/Syntaxerrors.ptx b/pretext/GeneralIntro/Syntaxerrors.ptx index 033e6ad93..ef3ac5a61 100644 --- a/pretext/GeneralIntro/Syntaxerrors.ptx +++ b/pretext/GeneralIntro/Syntaxerrors.ptx @@ -16,7 +16,7 @@

    Check your understanding

    - +

    Which of the following is a syntax error?

    @@ -47,7 +47,7 @@
    - +

    Who or what typically finds syntax errors?

    diff --git a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx index 7063970cc..ff6c7ed7a 100644 --- a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx +++ b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx @@ -74,7 +74,7 @@ My first program adds two numbers, 2 and 3:

    Check your understanding

    - +

    Source code is another name for:

    @@ -113,7 +113,7 @@ My first program adds two numbers, 2 and 3:
    - +

    What is the difference between a high-level programming language and a low-level programming language?

    @@ -154,7 +154,7 @@ My first program adds two numbers, 2 and 3: - +

    Pick the best replacements for 1 and 2 in the following sentence: When comparing compilers and interpreters, a compiler is like 1 while an interpreter is like 2.

    diff --git a/pretext/GeneralIntro/WhatisDebugging.ptx b/pretext/GeneralIntro/WhatisDebugging.ptx index 5be266672..5d065d654 100644 --- a/pretext/GeneralIntro/WhatisDebugging.ptx +++ b/pretext/GeneralIntro/WhatisDebugging.ptx @@ -12,7 +12,7 @@

    Check your understanding

    - +

    Debugging is:

    diff --git a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx index 8d320b2c4..84fafc779 100644 --- a/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx +++ b/pretext/GeneralIntro/intro-TheWayoftheProgram.ptx @@ -1,7 +1,7 @@
    The Way of the Program -

    The goal of this book is to be really awesome, and if there's time after that I guess we can also teach you to think like a computer scientist. This +

    The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas (specifically computations). Like engineers, they From 98bd4e55005963e54f37afc782040e06511f0258 Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:21:09 -0600 Subject: [PATCH 30/90] Update ThewhileStatement.rst user input does not work with codelens --- _sources/MoreAboutIteration/ThewhileStatement.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sources/MoreAboutIteration/ThewhileStatement.rst b/_sources/MoreAboutIteration/ThewhileStatement.rst index 7b68775de..8d08fa036 100644 --- a/_sources/MoreAboutIteration/ThewhileStatement.rst +++ b/_sources/MoreAboutIteration/ThewhileStatement.rst @@ -101,7 +101,7 @@ The same program in codelens will allow you to observe the flow of execution. .. codelens:: ch07_while3 """ Return the sum of 1+2+3 ... n """ - aBound = int(input("Please give a number n: ")) + aBound = 10 theSum = 0 aNumber = 1 while aNumber <= aBound: From 091c6eeaa7c22820255cff934ac552c09e3ef2fc Mon Sep 17 00:00:00 2001 From: robotuw Date: Tue, 13 Jun 2023 11:42:43 -0600 Subject: [PATCH 31/90] Bug Test Checking if simply changing codelens activities to activecode fixes the issue of them not showing up in the Runestone hosted instance. --- pretext/Strings/TraversalandtheforLoopByIndex.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Strings/TraversalandtheforLoopByIndex.ptx b/pretext/Strings/TraversalandtheforLoopByIndex.ptx index baaa97702..fbaead88e 100644 --- a/pretext/Strings/TraversalandtheforLoopByIndex.ptx +++ b/pretext/Strings/TraversalandtheforLoopByIndex.ptx @@ -5,7 +5,7 @@ These positions can be used together with the indexing operator to access the individual characters in the string.

    Consider the following codelens example.

    - + fruit = "apple" for idx in range(5): @@ -27,7 +27,7 @@ for idx in range(len(fruit)):

    You may also note that iteration by position allows the programmer to control the direction of the traversal by changing the sequence of index values. Recall that we can create ranges that count down as well as up so the following code will print the characters from right to left.

    - + fruit = "apple" for idx in range(len(fruit)-1, -1, -1): From c9bb0d6afb7484393bb17731a29de8b4129dd0f8 Mon Sep 17 00:00:00 2001 From: robotuw Date: Tue, 13 Jun 2023 16:49:30 -0600 Subject: [PATCH 32/90] Chapters 3-8 Overhaul Major order changes to subchapters in sections 3 through 8. --- .../ListComprehensions.ptx | 0 pretext/AdditionalTopics/toctree.ptx | 5 + .../Afindfunction.ptx | 0 pretext/{Lists => ComplexLogic}/Aliasing.ptx | 0 .../{Lists => ComplexLogic}/CloningLists.ptx | 0 .../FunctionsthatProduceLists.ptx | 0 .../Loopingandcounting.ptx | 0 .../{Lists => ComplexLogic}/NestedLists.ptx | 0 .../ObjectsandReferences.ptx | 0 .../Optionalparameters.ptx | 0 .../{Lists => ComplexLogic}/PureFunctions.ptx | 0 .../RepetitionandReferences.ptx | 0 .../TheAccumulatorPatternwithLists.ptx | 0 .../TheAccumulatorPatternwithStrings.ptx | 0 .../UsingListsasParameters.ptx | 0 .../{Lists => ComplexLogic}/WhichisBetter.ptx | 0 pretext/ComplexLogic/intro_ComplexLogic.ptx | 94 ++++++++++ pretext/ComplexLogic/toctree.ptx | 21 +++ .../BooleanFunctions.ptx | 0 pretext/Functions/toctree.ptx | 1 + .../2DimensionalIterationImageProcessing.ptx | 0 .../AlgorithmsRevisited.ptx | 0 .../BreakAndContinue.ptx | 12 +- .../Exercises.ptx | 0 .../FlowofExecutionofthewhileLoop.ptx | 4 +- .../Glossary.ptx | 0 .../ImageProcessingonYourOwn.ptx | 0 .../{Lists => Iteration}/Listsandforloops.ptx | 2 +- .../NewtonsMethod.ptx | 14 +- .../RandomlyWalkingTurtles.ptx | 0 .../SentinelValuesAndValidation.ptx | 8 +- .../SimpleTables.ptx | 0 .../The3n1Sequence.ptx | 4 +- .../TheforLoop.ptx | 19 +- .../Theforlooprevisited.ptx | 0 .../TherangeFunction.ptx | 10 +- .../ThewhileStatement.ptx | 17 +- .../TraversalandtheforLoopByIndex.ptx | 2 +- .../TraversalandtheforLoopByItem.ptx | 2 +- .../TraversalandthewhileLoop.ptx | 2 +- .../accumulatorRevisited.ptx | 0 .../intro-Iteration.ptx} | 4 +- .../toctree.ptx | 13 +- pretext/Lists/ListSlices.ptx | 8 +- pretext/Lists/toctree.ptx | 16 -- .../BooleanValuesandBooleanExpressions.ptx | 2 +- .../ConditionalExecutionBinarySelection.ptx | 23 ++- .../{Lists => Selection}/ListMembership.ptx | 0 .../OmittingtheelseClauseUnarySelection.ptx | 2 +- .../StringComparison.ptx | 0 .../Theinandnotinoperators.ptx | 0 pretext/Selection/toctree.ptx | 6 +- pretext/Strings/StringMethods.ptx | 176 ------------------ pretext/Strings/fStrings.ptx | 169 +++++++++++++++++ pretext/Strings/toctree.ptx | 10 +- pretext/thinkcspy.ptx | 16 +- 56 files changed, 379 insertions(+), 283 deletions(-) rename pretext/{Lists => AdditionalTopics}/ListComprehensions.ptx (100%) create mode 100644 pretext/AdditionalTopics/toctree.ptx rename pretext/{Strings => ComplexLogic}/Afindfunction.ptx (100%) rename pretext/{Lists => ComplexLogic}/Aliasing.ptx (100%) rename pretext/{Lists => ComplexLogic}/CloningLists.ptx (100%) rename pretext/{Lists => ComplexLogic}/FunctionsthatProduceLists.ptx (100%) rename pretext/{Strings => ComplexLogic}/Loopingandcounting.ptx (100%) rename pretext/{Lists => ComplexLogic}/NestedLists.ptx (100%) rename pretext/{Lists => ComplexLogic}/ObjectsandReferences.ptx (100%) rename pretext/{Strings => ComplexLogic}/Optionalparameters.ptx (100%) rename pretext/{Lists => ComplexLogic}/PureFunctions.ptx (100%) rename pretext/{Lists => ComplexLogic}/RepetitionandReferences.ptx (100%) rename pretext/{Lists => ComplexLogic}/TheAccumulatorPatternwithLists.ptx (100%) rename pretext/{Strings => ComplexLogic}/TheAccumulatorPatternwithStrings.ptx (100%) rename pretext/{Lists => ComplexLogic}/UsingListsasParameters.ptx (100%) rename pretext/{Lists => ComplexLogic}/WhichisBetter.ptx (100%) create mode 100644 pretext/ComplexLogic/intro_ComplexLogic.ptx create mode 100644 pretext/ComplexLogic/toctree.ptx rename pretext/{Selection => Functions}/BooleanFunctions.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/2DimensionalIterationImageProcessing.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/AlgorithmsRevisited.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/BreakAndContinue.ptx (81%) rename pretext/{MoreAboutIteration => Iteration}/Exercises.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/FlowofExecutionofthewhileLoop.ptx (82%) rename pretext/{MoreAboutIteration => Iteration}/Glossary.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/ImageProcessingonYourOwn.ptx (100%) rename pretext/{Lists => Iteration}/Listsandforloops.ptx (98%) rename pretext/{MoreAboutIteration => Iteration}/NewtonsMethod.ptx (95%) rename pretext/{MoreAboutIteration => Iteration}/RandomlyWalkingTurtles.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/SentinelValuesAndValidation.ptx (95%) rename pretext/{MoreAboutIteration => Iteration}/SimpleTables.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/The3n1Sequence.ptx (99%) rename pretext/{MoreAboutIteration => Iteration}/TheforLoop.ptx (79%) rename pretext/{MoreAboutIteration => Iteration}/Theforlooprevisited.ptx (100%) rename pretext/{MoreAboutIteration => Iteration}/TherangeFunction.ptx (96%) rename pretext/{MoreAboutIteration => Iteration}/ThewhileStatement.ptx (90%) rename pretext/{Strings => Iteration}/TraversalandtheforLoopByIndex.ptx (98%) rename pretext/{Strings => Iteration}/TraversalandtheforLoopByItem.ptx (98%) rename pretext/{Strings => Iteration}/TraversalandthewhileLoop.ptx (95%) rename pretext/{MoreAboutIteration => Iteration}/accumulatorRevisited.ptx (100%) rename pretext/{MoreAboutIteration/intro-IterationRevisited.ptx => Iteration/intro-Iteration.ptx} (77%) rename pretext/{MoreAboutIteration => Iteration}/toctree.ptx (68%) rename pretext/{Lists => Selection}/ListMembership.ptx (100%) rename pretext/{Strings => Selection}/StringComparison.ptx (100%) rename pretext/{Strings => Selection}/Theinandnotinoperators.ptx (100%) create mode 100644 pretext/Strings/fStrings.ptx diff --git a/pretext/Lists/ListComprehensions.ptx b/pretext/AdditionalTopics/ListComprehensions.ptx similarity index 100% rename from pretext/Lists/ListComprehensions.ptx rename to pretext/AdditionalTopics/ListComprehensions.ptx diff --git a/pretext/AdditionalTopics/toctree.ptx b/pretext/AdditionalTopics/toctree.ptx new file mode 100644 index 000000000..ad7c68063 --- /dev/null +++ b/pretext/AdditionalTopics/toctree.ptx @@ -0,0 +1,5 @@ + + +4Additional Topics +4 + diff --git a/pretext/Strings/Afindfunction.ptx b/pretext/ComplexLogic/Afindfunction.ptx similarity index 100% rename from pretext/Strings/Afindfunction.ptx rename to pretext/ComplexLogic/Afindfunction.ptx diff --git a/pretext/Lists/Aliasing.ptx b/pretext/ComplexLogic/Aliasing.ptx similarity index 100% rename from pretext/Lists/Aliasing.ptx rename to pretext/ComplexLogic/Aliasing.ptx diff --git a/pretext/Lists/CloningLists.ptx b/pretext/ComplexLogic/CloningLists.ptx similarity index 100% rename from pretext/Lists/CloningLists.ptx rename to pretext/ComplexLogic/CloningLists.ptx diff --git a/pretext/Lists/FunctionsthatProduceLists.ptx b/pretext/ComplexLogic/FunctionsthatProduceLists.ptx similarity index 100% rename from pretext/Lists/FunctionsthatProduceLists.ptx rename to pretext/ComplexLogic/FunctionsthatProduceLists.ptx diff --git a/pretext/Strings/Loopingandcounting.ptx b/pretext/ComplexLogic/Loopingandcounting.ptx similarity index 100% rename from pretext/Strings/Loopingandcounting.ptx rename to pretext/ComplexLogic/Loopingandcounting.ptx diff --git a/pretext/Lists/NestedLists.ptx b/pretext/ComplexLogic/NestedLists.ptx similarity index 100% rename from pretext/Lists/NestedLists.ptx rename to pretext/ComplexLogic/NestedLists.ptx diff --git a/pretext/Lists/ObjectsandReferences.ptx b/pretext/ComplexLogic/ObjectsandReferences.ptx similarity index 100% rename from pretext/Lists/ObjectsandReferences.ptx rename to pretext/ComplexLogic/ObjectsandReferences.ptx diff --git a/pretext/Strings/Optionalparameters.ptx b/pretext/ComplexLogic/Optionalparameters.ptx similarity index 100% rename from pretext/Strings/Optionalparameters.ptx rename to pretext/ComplexLogic/Optionalparameters.ptx diff --git a/pretext/Lists/PureFunctions.ptx b/pretext/ComplexLogic/PureFunctions.ptx similarity index 100% rename from pretext/Lists/PureFunctions.ptx rename to pretext/ComplexLogic/PureFunctions.ptx diff --git a/pretext/Lists/RepetitionandReferences.ptx b/pretext/ComplexLogic/RepetitionandReferences.ptx similarity index 100% rename from pretext/Lists/RepetitionandReferences.ptx rename to pretext/ComplexLogic/RepetitionandReferences.ptx diff --git a/pretext/Lists/TheAccumulatorPatternwithLists.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx similarity index 100% rename from pretext/Lists/TheAccumulatorPatternwithLists.ptx rename to pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx diff --git a/pretext/Strings/TheAccumulatorPatternwithStrings.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx similarity index 100% rename from pretext/Strings/TheAccumulatorPatternwithStrings.ptx rename to pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx diff --git a/pretext/Lists/UsingListsasParameters.ptx b/pretext/ComplexLogic/UsingListsasParameters.ptx similarity index 100% rename from pretext/Lists/UsingListsasParameters.ptx rename to pretext/ComplexLogic/UsingListsasParameters.ptx diff --git a/pretext/Lists/WhichisBetter.ptx b/pretext/ComplexLogic/WhichisBetter.ptx similarity index 100% rename from pretext/Lists/WhichisBetter.ptx rename to pretext/ComplexLogic/WhichisBetter.ptx diff --git a/pretext/ComplexLogic/intro_ComplexLogic.ptx b/pretext/ComplexLogic/intro_ComplexLogic.ptx new file mode 100644 index 000000000..a1e119c58 --- /dev/null +++ b/pretext/ComplexLogic/intro_ComplexLogic.ptx @@ -0,0 +1,94 @@ + +
    + Complex Logic Introduction +

    Recall that the for loop processes each item in a list. Each item in + turn is (re-)assigned to the loop variable, and the body of the loop is executed. + We saw this example in an earlier chapter.

    + + +for f in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: + print("Hi", f, "Please come to my party on Saturday") + + +

    We have also seen iteration paired with the update idea to form the accumulator pattern. For example, to compute + the sum of the first n integers, we could create a for loop using the range to produce the numbers 1 through n. + Using the accumulator pattern, we can start with a running total variable initialized to 0 and on each iteration, add the current value of the loop + variable. A function to compute this sum is shown below.

    + + +def sumTo(aBound): + theSum = 0 + for aNumber in range(1, aBound + 1): + theSum = theSum + aNumber + + return theSum + +print(sumTo(4)) + +print(sumTo(1000)) + + +

    To review, the variable theSum is called the accumulator. It is initialized to zero before we start the loop. The loop variable, aNumber will take on the values produced by the range(1, aBound + 1) function call. Note that this produces all the integers from 1 up to the value of aBound. If we had not added 1 to aBound, the range would have stopped one value short since range does not include the upper bound.

    +

    The assignment statement, theSum = theSum + aNumber, updates theSum each time through the loop. This accumulates the running total. Finally, we return the value of the accumulator.

    +

    + Check Your Understanding +

    + + +

    The following code contains an nested loop. How many times will the phrase We made it here! be printed on the console?

    + + +def printnums(x,y): + for h in range(y): + print("We made it here!") + for i in range(x): + print("We made it here!") + +printnums(5, 3) + + +
    + + + +

    5

    +
    + + This is how many times the inner loop will print for each iteration of the outer loop. + +
    + + +

    8

    +
    + + Keep in mind that the inner loop is part of the body of the outer loop. + +
    + + +

    15

    +
    + + The inner loop will print a total of 15 times; however the outer loop is also printing the same phrase. + +
    + + +

    18

    +
    + + Correct! The nested loop will be run 3 times, making a total of 18. + +
    + + +

    20

    +
    + + Pay attention to the order of x and y + +
    +
    +
    +
    diff --git a/pretext/ComplexLogic/toctree.ptx b/pretext/ComplexLogic/toctree.ptx new file mode 100644 index 000000000..9601f6732 --- /dev/null +++ b/pretext/ComplexLogic/toctree.ptx @@ -0,0 +1,21 @@ + + +4Complex Logic +4 + +4 +4 +4 +4 + +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 + diff --git a/pretext/Selection/BooleanFunctions.ptx b/pretext/Functions/BooleanFunctions.ptx similarity index 100% rename from pretext/Selection/BooleanFunctions.ptx rename to pretext/Functions/BooleanFunctions.ptx diff --git a/pretext/Functions/toctree.ptx b/pretext/Functions/toctree.ptx index a67c2ddc1..d636c2e55 100644 --- a/pretext/Functions/toctree.ptx +++ b/pretext/Functions/toctree.ptx @@ -7,6 +7,7 @@ 4 4 4 +4 4 4 4 diff --git a/pretext/MoreAboutIteration/2DimensionalIterationImageProcessing.ptx b/pretext/Iteration/2DimensionalIterationImageProcessing.ptx similarity index 100% rename from pretext/MoreAboutIteration/2DimensionalIterationImageProcessing.ptx rename to pretext/Iteration/2DimensionalIterationImageProcessing.ptx diff --git a/pretext/MoreAboutIteration/AlgorithmsRevisited.ptx b/pretext/Iteration/AlgorithmsRevisited.ptx similarity index 100% rename from pretext/MoreAboutIteration/AlgorithmsRevisited.ptx rename to pretext/Iteration/AlgorithmsRevisited.ptx diff --git a/pretext/MoreAboutIteration/BreakAndContinue.ptx b/pretext/Iteration/BreakAndContinue.ptx similarity index 81% rename from pretext/MoreAboutIteration/BreakAndContinue.ptx rename to pretext/Iteration/BreakAndContinue.ptx index 1c0420543..8f13f7198 100644 --- a/pretext/MoreAboutIteration/BreakAndContinue.ptx +++ b/pretext/Iteration/BreakAndContinue.ptx @@ -3,7 +3,7 @@ <c>break</c> and <c>continue</c>

    In loops, we sometimes want to traverse until we reach a certain value. - We could make some sort of loop condition with a boolean that is toggled as True once we + We could make a loop condition with a boolean that is toggled as True once we reach that value, but there's an easier way: the break statement.

    When a break statement is reached, the loop immediately ends and proceeds with the code after the loop. @@ -11,10 +11,12 @@ -for i in range(0, 10): +i = 0 +while i < 10: if i == 5: break print(i) + i += 1 @@ -24,13 +26,15 @@ for i in range(0, 10): -for i in range(0, 10): +i = 0 +while i < 10: if i == 5: continue print(i) + i += 1 Notice the difference between the activecode example above for break and this example with continue. - Neither loop reaches 5, but in the loop with continue, it continues iterating after where 5 would have been. + Neither loop prints 5, but in the loop with continue, it continues iterating after where 5 would have been.

    diff --git a/pretext/MoreAboutIteration/Exercises.ptx b/pretext/Iteration/Exercises.ptx similarity index 100% rename from pretext/MoreAboutIteration/Exercises.ptx rename to pretext/Iteration/Exercises.ptx diff --git a/pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx similarity index 82% rename from pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx rename to pretext/Iteration/FlowofExecutionofthewhileLoop.ptx index 0e6ec1c18..674266a21 100644 --- a/pretext/MoreAboutIteration/FlowofExecutionofthewhileLoop.ptx +++ b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx @@ -1,10 +1,10 @@
    Flow of Execution of the while Loop -

    As before with ``if``, loops allow us as programmers to manipulate the control flow of a Python program. +

    As before with if, loops allow us as programmers to manipulate the control flow of a Python program. We can now possibly skip a portion of code, or choose to repeat it an indefinite number of times.

    The flowchart below provides the general sequence of steps that govern execution of a while loop.

    - +

    A codelens demonstration is a good way to help you visualize exactly how the flow of control works with the while loop. Try stepping forward and backward through the program by pressing the buttons. You can see the value of count change as the loop iterates through the values from 10 to 0.

    diff --git a/pretext/MoreAboutIteration/Glossary.ptx b/pretext/Iteration/Glossary.ptx similarity index 100% rename from pretext/MoreAboutIteration/Glossary.ptx rename to pretext/Iteration/Glossary.ptx diff --git a/pretext/MoreAboutIteration/ImageProcessingonYourOwn.ptx b/pretext/Iteration/ImageProcessingonYourOwn.ptx similarity index 100% rename from pretext/MoreAboutIteration/ImageProcessingonYourOwn.ptx rename to pretext/Iteration/ImageProcessingonYourOwn.ptx diff --git a/pretext/Lists/Listsandforloops.ptx b/pretext/Iteration/Listsandforloops.ptx similarity index 98% rename from pretext/Lists/Listsandforloops.ptx rename to pretext/Iteration/Listsandforloops.ptx index 0d84e038d..872c053ab 100644 --- a/pretext/Lists/Listsandforloops.ptx +++ b/pretext/Iteration/Listsandforloops.ptx @@ -1,6 +1,6 @@
    - Lists and <c>for</c> loops + Traversing lists with the <c>for</c> loop

    It is also possible to perform list traversal using iteration by item as well as iteration by index.

    diff --git a/pretext/MoreAboutIteration/NewtonsMethod.ptx b/pretext/Iteration/NewtonsMethod.ptx similarity index 95% rename from pretext/MoreAboutIteration/NewtonsMethod.ptx rename to pretext/Iteration/NewtonsMethod.ptx index 755a5b205..7a46fbdbe 100644 --- a/pretext/MoreAboutIteration/NewtonsMethod.ptx +++ b/pretext/Iteration/NewtonsMethod.ptx @@ -21,14 +21,14 @@ better = 1/2 * (approx + n/approx) calculation yielding a better result.

    - n = 100 - howmany = 10 +n = 100 +howmany = 10 - approx = 0.5 * n - for i in range(howmany): - betterapprox = 0.5 * (approx + n/approx) - approx = betterapprox - prin(betterapprox) +approx = 0.5 * n +for i in range(howmany): + betterapprox = 0.5 * (approx + n/approx) + approx = betterapprox +prin(betterapprox) diff --git a/pretext/MoreAboutIteration/RandomlyWalkingTurtles.ptx b/pretext/Iteration/RandomlyWalkingTurtles.ptx similarity index 100% rename from pretext/MoreAboutIteration/RandomlyWalkingTurtles.ptx rename to pretext/Iteration/RandomlyWalkingTurtles.ptx diff --git a/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx b/pretext/Iteration/SentinelValuesAndValidation.ptx similarity index 95% rename from pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx rename to pretext/Iteration/SentinelValuesAndValidation.ptx index fb2201e90..cbc33af57 100644 --- a/pretext/MoreAboutIteration/SentinelValuesAndValidation.ptx +++ b/pretext/Iteration/SentinelValuesAndValidation.ptx @@ -3,7 +3,7 @@ Other uses of <c>while</c> Sentinel Values -

    The indefinite loops provided by the ``while`` statement are common in the real world.

    +

    The indefinite loops provided by the while statement are common in the real world.

    • @@ -86,8 +86,8 @@ division by zero and tell the user that you can't compute an average without data.

    • -

      This program doesn't display the amounts to two decimal places. In the next chapter you will - see the that will do the trick.

      +

      This program doesn't display the amounts to two decimal places. Thankfully, you already know how to fix this issue. + Recall how you learned to format floats to a specific number of decimal points in .

      Check your understanding

      @@ -125,7 +125,7 @@ that asks a yes-or-no question. In this case, you want to make sure that the person using your program enters either a Y for yes or N for no (in either upper or lower case). Here is a program that uses a while loop to keep asking until it receives a valid answer. - As a preview of coming attractions, it uses + Note that it uses the upper() method which is described in to convert a string to upper case. When you run the following code, try typing something other than Y or N to see how the code reacts:

      diff --git a/pretext/MoreAboutIteration/SimpleTables.ptx b/pretext/Iteration/SimpleTables.ptx similarity index 100% rename from pretext/MoreAboutIteration/SimpleTables.ptx rename to pretext/Iteration/SimpleTables.ptx diff --git a/pretext/MoreAboutIteration/The3n1Sequence.ptx b/pretext/Iteration/The3n1Sequence.ptx similarity index 99% rename from pretext/MoreAboutIteration/The3n1Sequence.ptx rename to pretext/Iteration/The3n1Sequence.ptx index 2c8cdcaa4..40e4c4150 100644 --- a/pretext/MoreAboutIteration/The3n1Sequence.ptx +++ b/pretext/Iteration/The3n1Sequence.ptx @@ -47,7 +47,7 @@

      You'll notice that if you don't stop when you reach one, the sequence gets into its own loop: 1, 4, 2, 1, 4, 2, 1, 4, and so on. One possibility is that there might be other cycles that we just haven't found.

      - + diff --git a/pretext/MoreAboutIteration/TheforLoop.ptx b/pretext/Iteration/TheforLoop.ptx similarity index 79% rename from pretext/MoreAboutIteration/TheforLoop.ptx rename to pretext/Iteration/TheforLoop.ptx index d98fc4484..3b4d6bc78 100644 --- a/pretext/MoreAboutIteration/TheforLoop.ptx +++ b/pretext/Iteration/TheforLoop.ptx @@ -2,7 +2,7 @@
      The <c>for</c> loop

      The while statement is a general-purpose tool for iteration, and is necessary for any instance of iteration where we don't know how many repetitions will be needed. -However, if we do know how many are needed, there is a more efficient method: the for statement.

      +However, if we do know how many are needed, there is a more efficient approach: the for statement.

      As a simple example, let's say we have some friends, and we'd like to send them each an email inviting them to our party. We don't quite know how to send email yet, so for the moment we'll just print a @@ -15,12 +15,13 @@ message for each friend.

      Take a look at the output produced when you press the run button. There is one line printed for each friend. Here's how it works:

        -
      • name in this for statement is the loop variable.
      • -
      • The list of names in the square brackets is a regular list. Later we'll see that other types besides lists can be put in this spot.
      • -
      • Line 2 is the loop body. Like with while, the loop body is always indented. The loop body is performed one time for each name in the list.
      • +
      • name is the loop variable in this case.
      • +
      • Frustratingly, in here is not the same as the keyword used to check for membership. This just a necessary part of every for loop construction and not an operator.
      • +
      • The list of names in the square brackets is a regular list. Later we'll see that other types besides lists can be put in this spot.
      • +
      • Line 2 is the loop body. Like with while, the loop body is always indented. The loop body is performed one time for each name in the list.
      • On each iteration or pass of the loop, a check is done to see if there are still more items to be processed. If there are none left (this is - called the terminating condition of the loop), the loop has finished. + called the terminating condition of the loop), the loop has finished. Program execution continues at the next statement after the loop body.
      • If there are items still to be processed, the loop variable is updated to refer to the next item in the list. This means, in this case, that the loop @@ -34,10 +35,10 @@ message for each friend.

        Introduction of the for statement causes us to think about the types of iteration we have seen. The for statement will always iterate through a sequence of values like the list of names for the party.

        Since we know that it will iterate once for each value in the collection, it is often said that a for loop creates a - definite iteration because we definitely know how many times we are going to iterate. On the other + definite iteration because we definitely know how many times we are going to iterate. On the other hand, the while statement is dependent on a condition that needs to evaluate to False in order for the loop to terminate. Since we do not necessarily know when this will happen, it creates what we - call indefinite iteration. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition + call indefinite iteration. Indefinite iteration simply means that we don't know how many times we will repeat but eventually the condition controlling the iteration will fail and the iteration will stop. (Unless we have an infinite loop which is of course a problem.)

        @@ -49,7 +50,7 @@ message for each friend.

        So any problem like "iterate this weather model run for 1000 cycles", or "search this list of words", "check all integers up to 10000 to see which are prime" suggest that a for loop is best.

        By contrast, if you are required to repeat some computation until some condition is - met, as we did in this 3n + 1 problem, you'll need a while loop.

        + met, as we did in the 3n + 1 problem last week, you'll need a while loop.

        What you will notice here is that the while loop is more work for @@ -58,7 +59,7 @@ loop you have to control the loop variable yourself. You give it an initial val for completion, and then make sure you change something in the body so that the loop terminates.

        - <b>Check your understanding</b> + Check your understanding diff --git a/pretext/MoreAboutIteration/Theforlooprevisited.ptx b/pretext/Iteration/Theforlooprevisited.ptx similarity index 100% rename from pretext/MoreAboutIteration/Theforlooprevisited.ptx rename to pretext/Iteration/Theforlooprevisited.ptx diff --git a/pretext/MoreAboutIteration/TherangeFunction.ptx b/pretext/Iteration/TherangeFunction.ptx similarity index 96% rename from pretext/MoreAboutIteration/TherangeFunction.ptx rename to pretext/Iteration/TherangeFunction.ptx index 05f9fdbaa..a3bd46c3b 100644 --- a/pretext/MoreAboutIteration/TherangeFunction.ptx +++ b/pretext/Iteration/TherangeFunction.ptx @@ -1,11 +1,11 @@
        The range Function -

You should experiment with these @@ -335,169 +324,4 @@ print(s[1] * s.index("n")) - - F-Strings -

In grade school quizzes a common convention is to use fill-in-the blanks. For instance,

-
-

Hello _____!

-
-

and you can fill in the name of the person greeted, and combine - given text with a chosen insertion. We use this as an analogy: - Python has a similar - construction, called a formatted string or an f-string. An f-string makes - substitutions into places in a string - enclosed in braces. Run this code:

- - -person = input('Your name: ') -greeting = f'Hello {person}!' -print(greeting) - - -

There are several new ideas here!

-

The string has been formatted in a new way. We have included an f before the starting quotation mark. - Such a string is called an f-string. Places where - braces are embedded are replaced by the value of the expression inside the braces. There are many - variations on the syntax between the braces. In this case we use - the syntax where the first (and only) location in the string with - braces has the variable person. When this code is evaluated, the value of the person variable is placed in the string in this location.

-

In the code above, this new string is assigned to the identifier - greeting, and then the string is printed.

-

The identifier - greeting was introduced to break the operations into a clearer - sequence of steps. However, since the value of greeting is only - referenced once, it can be eliminated with the more concise - version:

- - -person = input('Enter your name: ') -print(f'Hello {person}!') - - -

There can be multiple substitutions, with data of any type. - Next we use floats. Try original price $2.50 with a 7% discount:

- - -origPrice = float(input('Enter the original price: $')) -discount = float(input('Enter discount percentage: ')) -newPrice = (1 - discount/100)*origPrice -calculation = f'${origPrice} discounted by {discount}% is ${newPrice}.' -print(calculation) - - -

If you used the data suggested, this result is not satisfying. - Prices should appear with exactly two places beyond the decimal point, - but that is not the default way to display floats.

-

F-strings can give further information inside the braces - showing how to specially format data. - In particular floats can be shown with a specific number of decimal places. - For two decimal places, put :.2f inside the braces but after the variable name for the monetary values:

- - -origPrice = float(input('Enter the original price: $')) -discount = float(input('Enter discount percentage: ')) -newPrice = (1 - discount/100)*origPrice -calculation = f'${origPrice:.2f} discounted by {discount}% is ${newPrice:.2f}.' -print(calculation) - - -

The 2 in the format modifier can be replaced by another integer to round to that - specified number of digits.

-

A technical point: Since braces have special meaning in a format - string, there must be a special rule if you want braces to actually - be included in the final formatted string. The rule is to double - the braces: { { and }}. For example mathematical set - notation uses braces. The initial and final doubled - braces in the format string below generate literal braces in the - formatted string:

-
a = 5
-b = 9
-setStr = f'The set is {​{ {a},{b} }​}.'
-print(setStr)
-

Unfortunately, at the time of this writing, the ActiveCode format implementation has a bug, - printing doubled braces, but standard Python prints {5, 9}.

- - -

What is printed by the following statements?

- - -x = 2 -y = 6 -print(f'sum of {x} and {y} is {x+y}; product: {x*y}.') - - -
- - - -

Nothing - it causes an error

-
- - It is legal format syntax. - -
- - -

sum of {} and {} is {}; product: {}.

-
- - Put the value of each expression in place of the braces. - -
- - -

sum of 2 and 6 is 8; product: 12.

-
- - Yes, correct! - -
- - -

sum of {2} and {6} is {8}; product: {12}.

-
- - Close: REPLACE the braces. - -
-
-
- - -

What is printed by the following statements?

- - -v = 2.34567 -print(f'{v:.1f} {v:.2f} {v:.7f}') - - -
- - - -

2.34567 2.34567 2.34567

-
- - The numbers before the f in the braces give the number of digits to display after the decimal point. - -
- - -

2.3 2.34 2.34567

-
- - Close, but round to the number of digits and display the full number of digits specified. - -
- - -

2.3 2.35 2.3456700

-
- - Yes, correct number of digits with rounding! - -
-
-
-
diff --git a/pretext/Strings/fStrings.ptx b/pretext/Strings/fStrings.ptx new file mode 100644 index 000000000..8b4522ef0 --- /dev/null +++ b/pretext/Strings/fStrings.ptx @@ -0,0 +1,169 @@ + +
+ F-Strings + +

In grade school quizzes a common convention is to use fill-in-the blanks. For instance,

+
+

Hello _____!

+
+

and you can fill in the name of the person greeted, and combine + given text with a chosen insertion. We use this as an analogy: + Python has a similar + construction, called a formatted string or an f-string. An f-string makes + substitutions into places in a string + enclosed in braces. Run this code:

+
+ + + +person = input('Your name: ') +greeting = f'Hello {person}!' +print(greeting) + + +

There are several new ideas here!

+

The string has been formatted in a new way. We have included an f before the starting quotation mark. + Such a string is called an f-string. Places where + braces are embedded are replaced by the value of the expression inside the braces. There are many + variations on the syntax between the braces. In this case we use + the syntax where the first (and only) location in the string with + braces has the variable person. When this code is evaluated, the value of the person variable is placed in the string in this location.

+

In the code above, this new string is assigned to the identifier + greeting, and then the string is printed.

+

The identifier + greeting was introduced to break the operations into a clearer + sequence of steps. However, since the value of greeting is only + referenced once, it can be eliminated with the more concise + version:

+ + +person = input('Enter your name: ') +print(f'Hello {person}!') + + +

There can be multiple substitutions, with data of any type. + Next we use floats. Try original price $2.50 with a 7% discount:

+ + +origPrice = float(input('Enter the original price: $')) +discount = float(input('Enter discount percentage: ')) +newPrice = (1 - discount/100)*origPrice +calculation = f'${origPrice} discounted by {discount}% is ${newPrice}.' +print(calculation) + + +

If you used the data suggested, this result is not satisfying. + Prices should appear with exactly two places beyond the decimal point, + but that is not the default way to display floats.

+

F-strings can give further information inside the braces + showing how to specially format data. + In particular, floats can be shown with a specific number of decimal places. + For two decimal places, put :.2f inside the braces but after the variable name for the monetary values:

+ + +origPrice = float(input('Enter the original price: $')) +discount = float(input('Enter discount percentage: ')) +newPrice = (1 - discount/100)*origPrice +calculation = f'${origPrice:.2f} discounted by {discount}% is ${newPrice:.2f}.' +print(calculation) + + +

The 2 in the format modifier can be replaced by another integer to round to that + specified number of digits.

+

A technical point: Since braces have special meaning in a format + string, there must be a special rule if you want braces to actually + be included in the final formatted string. The rule is to double + the braces: { { and }}. For example mathematical set + notation uses braces. The initial and final doubled + braces in the format string below generate literal braces in the + formatted string:

+
a = 5
+b = 9
+setStr = f'The set is {​{ {a},{b} }​}.'
+print(setStr)
+

Unfortunately, at the time of this writing, the ActiveCode format implementation has a bug, + printing doubled braces, but standard Python prints {5, 9}.

+ + +

What is printed by the following statements?

+ + +x = 2 +y = 6 +print(f'sum of {x} and {y} is {x+y}; product: {x*y}.') + + +
+ + + +

Nothing - it causes an error

+
+ + It is legal format syntax. + +
+ + +

sum of {} and {} is {}; product: {}.

+
+ + Put the value of each expression in place of the braces. + +
+ + +

sum of 2 and 6 is 8; product: 12.

+
+ + Yes, correct! + +
+ + +

sum of {2} and {6} is {8}; product: {12}.

+
+ + Close: REPLACE the braces. + +
+
+
+ + +

What is printed by the following statements?

+ + +v = 2.34567 +print(f'{v:.1f} {v:.2f} {v:.7f}') + + +
+ + + +

2.34567 2.34567 2.34567

+
+ + The numbers before the f in the braces give the number of digits to display after the decimal point. + +
+ + +

2.3 2.34 2.34567

+
+ + Close, but round to the number of digits and display the full number of digits specified. + +
+ + +

2.3 2.35 2.3456700

+
+ + Yes, correct number of digits with rounding! + +
+
+
+
diff --git a/pretext/Strings/toctree.ptx b/pretext/Strings/toctree.ptx index 82ac396fa..2e60eed65 100644 --- a/pretext/Strings/toctree.ptx +++ b/pretext/Strings/toctree.ptx @@ -8,17 +8,9 @@ 4 4 4 +4 4 -4 -4 -4 -4 -4 -4 4 -4 -4 -4 4 4 4 diff --git a/pretext/thinkcspy.ptx b/pretext/thinkcspy.ptx index bb96187a5..7ab3c1a5f 100644 --- a/pretext/thinkcspy.ptx +++ b/pretext/thinkcspy.ptx @@ -17,20 +17,22 @@ - + + - - - - - - + + + + + + + From 97db00f952c289be698f0e35537561ddb36e9c65 Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 15 Jun 2023 16:31:49 -0600 Subject: [PATCH 33/90] Chapters 8-12 Update Another massive update to content and organization of chapters 8-12. --- .../ComplexLogic/NestedList_Navigation.ptx | 107 ++++ pretext/ComplexLogic/intro_ComplexLogic.ptx | 94 +-- pretext/ComplexLogic/toctree.ptx | 13 +- .../intro-HowtobeaSuccessfulProgrammer.ptx | 2 +- pretext/Debugging/toctree.ptx | 3 +- pretext/Files/Glossary.ptx | 20 + pretext/Files/ReadingCSV.ptx | 66 +++ pretext/Files/WritingCSV.ptx | 44 ++ pretext/Files/intro-WorkingwithDataFiles.ptx | 4 +- pretext/Files/toctree.ptx | 4 +- pretext/Functions/Exercises.ptx | 396 +------------ pretext/Functions/TheAccumulatorPattern.ptx | 6 +- pretext/Functions/UnitTesting.ptx | 4 +- pretext/Functions/functions.ptx | 2 +- pretext/Functions/toctree.ptx | 7 +- pretext/GeneralIntro/toctree.ptx | 1 - .../IntroRecursion/ProgrammingExercises.ptx | 102 +--- pretext/IntroRecursion/toctree.ptx | 1 - pretext/Iteration/Exercises.ptx | 558 +----------------- pretext/Iteration/toctree.ptx | 1 - .../{ComplexLogic => Lists}/CloningLists.ptx | 0 pretext/Lists/toctree.ptx | 2 +- pretext/PythonModules/modules.ptx | 2 +- pretext/PythonModules/toctree.ptx | 1 - pretext/Selection/Exercises.ptx | 169 +----- pretext/Selection/toctree.ptx | 1 - pretext/SimplePythonData/toctree.ptx | 1 - pretext/Strings/toctree.ptx | 1 - pretext/thinkcspy.ptx | 4 +- 29 files changed, 300 insertions(+), 1316 deletions(-) create mode 100644 pretext/ComplexLogic/NestedList_Navigation.ptx create mode 100644 pretext/Files/ReadingCSV.ptx create mode 100644 pretext/Files/WritingCSV.ptx rename pretext/{ComplexLogic => Lists}/CloningLists.ptx (100%) diff --git a/pretext/ComplexLogic/NestedList_Navigation.ptx b/pretext/ComplexLogic/NestedList_Navigation.ptx new file mode 100644 index 000000000..96184c757 --- /dev/null +++ b/pretext/ComplexLogic/NestedList_Navigation.ptx @@ -0,0 +1,107 @@ + +
+ Nested List Traversal +

Nested lists can be traversed the say way as other lists. However, the code to do so can easily get complicated and confusing. In this section let us + examine several example programs that perform this task.

+ +

The following program concerns a list of lists of names. In some cases, we may want to take nested list data and "un-nest" it. To do this, we need to + iterate through the outer list, and then construct another loop to iterate through each name in each sublist. In this program's case, we are simply printing each + name as we encounter it.

+ + +names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] +for sublist in names: + for name in sublist: + print(name) + + +

Nested lists can also be navigated by index rather than by value. This complicates the code somewhat, but gives us more flexibility for what can be done to each item. + In this example program, we visit each name and turn it lowercase.

+ + +names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] +for sublist_index in range(len(names)): + for name_index in range(len(names[sublist_index])): + names[sublist_index][name_index] = names[sublist_index][name_index].lower() +print(names) + + +

Note that in the above program it is very important that we use len(names[sublist_index]) in the second range call. Because the nested lists in this example + do not have the same length, we have to check the length of each sublist when setting up our nested for loop bounds. If we do not do this carefully, then we can easily + miss data or get an out of bounds exception. Consider a different, erroneous example:

+ + +names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] +for sublist_index in range(len(names)): + for name_index in range(len(names[0])): + names[sublist_index][name_index] = names[sublist_index][name_index].lower() +print(names) + + +

Nested lists can be used in many different contexts, but one more common use is to model 2D grids of data. Here is one last example that treats nested lists as a 2D coordinate plane + and finds the location of a single value in that plane. Note this example reverses the y axis, so y values increase as you travel downward. This is to match the indexing on the lists, + though we could model this as a more familiar coordinate system with some small changes.

+ + +coord = [['_', '_', '_', '_'], + ['_', '_', 'p', '_'], + ['_', '_', '_', '_'], + ['_', '_', '_', '_']] +for y in range(len(names)): + for x in range(len(coord[y])): + if coord[y][x] == 'p': + print(f'p is as coordinates (x={x}, y={y})') + + +

+ Check your understanding +

+ + +

What is printed by the following statements?

+ + +alist = [ [4, [True, False], 6, 8], [888, 999] ] +for a in alist: + for b in range(1, len(a)): + if type(a[b]) == type(a[b-1]): + print(a[b], end=" ") + + +
+ + + +

8 999

+
+ + Yes, you are correct. + +
+ + +

4 6 8 888 999

+
+ + You are correct that the code will treat the list with boolean value differently, but you are missing other aspects. Look again at the bounds of the inner loop. + +
+ + +

4 True False 6 8 888 999

+
+ + This would be the output for a full traversal of the data. However, this code cannot fully traverse the data since it has three levels of nesting and the code only reaches two levels. + +
+ + +

4 [True, False] 6 8 888 999

+
+ + This would be the correct output if the code traversed two levels of nesting and printed everything. However, the if statement is also doing something here. + +
+
+
+
diff --git a/pretext/ComplexLogic/intro_ComplexLogic.ptx b/pretext/ComplexLogic/intro_ComplexLogic.ptx index a1e119c58..31d30702c 100644 --- a/pretext/ComplexLogic/intro_ComplexLogic.ptx +++ b/pretext/ComplexLogic/intro_ComplexLogic.ptx @@ -1,94 +1,8 @@
Complex Logic Introduction -

Recall that the for loop processes each item in a list. Each item in - turn is (re-)assigned to the loop variable, and the body of the loop is executed. - We saw this example in an earlier chapter.

- - -for f in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: - print("Hi", f, "Please come to my party on Saturday") - - -

We have also seen iteration paired with the update idea to form the accumulator pattern. For example, to compute - the sum of the first n integers, we could create a for loop using the range to produce the numbers 1 through n. - Using the accumulator pattern, we can start with a running total variable initialized to 0 and on each iteration, add the current value of the loop - variable. A function to compute this sum is shown below.

- - -def sumTo(aBound): - theSum = 0 - for aNumber in range(1, aBound + 1): - theSum = theSum + aNumber - - return theSum - -print(sumTo(4)) - -print(sumTo(1000)) - - -

To review, the variable theSum is called the accumulator. It is initialized to zero before we start the loop. The loop variable, aNumber will take on the values produced by the range(1, aBound + 1) function call. Note that this produces all the integers from 1 up to the value of aBound. If we had not added 1 to aBound, the range would have stopped one value short since range does not include the upper bound.

-

The assignment statement, theSum = theSum + aNumber, updates theSum each time through the loop. This accumulates the running total. Finally, we return the value of the accumulator.

-

- Check Your Understanding -

- - -

The following code contains an nested loop. How many times will the phrase We made it here! be printed on the console?

- - -def printnums(x,y): - for h in range(y): - print("We made it here!") - for i in range(x): - print("We made it here!") - -printnums(5, 3) - - -
- - - -

5

-
- - This is how many times the inner loop will print for each iteration of the outer loop. - -
- - -

8

-
- - Keep in mind that the inner loop is part of the body of the outer loop. - -
- - -

15

-
- - The inner loop will print a total of 15 times; however the outer loop is also printing the same phrase. - -
- - -

18

-
- - Correct! The nested loop will be run 3 times, making a total of 18. - -
- - -

20

-
- - Pay attention to the order of x and y - -
-
-
+

Believe it or not, in the past seven weeks we've covered nearly all of the fundamental constructs within programming. + While there is certainly much more to learn and discover, virtually any programming language you will see in the future offers some form + of branching, looping, and function definition. That is not to say we have mastered these topics yet. This week of class and this chapter + focuses on revisiting these fundamental topics and deepening our mastery of them.

diff --git a/pretext/ComplexLogic/toctree.ptx b/pretext/ComplexLogic/toctree.ptx index 9601f6732..61940cb1b 100644 --- a/pretext/ComplexLogic/toctree.ptx +++ b/pretext/ComplexLogic/toctree.ptx @@ -2,18 +2,15 @@ 4Complex Logic 4 +4 +4 -4 -4 4 -4 -4 -4 -4 -4 -4 +4 4 + +4 4 4 4 diff --git a/pretext/Debugging/intro-HowtobeaSuccessfulProgrammer.ptx b/pretext/Debugging/intro-HowtobeaSuccessfulProgrammer.ptx index 6f79d7f52..32cc1ecd1 100644 --- a/pretext/Debugging/intro-HowtobeaSuccessfulProgrammer.ptx +++ b/pretext/Debugging/intro-HowtobeaSuccessfulProgrammer.ptx @@ -1,6 +1,6 @@
How to be a Successful Programmer -

One of the most important skills you need to aquire to complete this book successfully is the ability to debug your programs. Debugging might be the most under-appreciated, and under-taught, skill in introductory computer science. For that reason we are introducing a series of debugging interludes. Debugging is a skill that you need to master over time, and some of the tips and tricks are specific to different aspects of Python programming. So look for additional debugging interludes throughout the rest of this book.

+

One of the most important skills you need to aquire to complete this book successfully is the ability to debug your programs. Debugging might be the most under-appreciated, and under-taught, skill in introductory computer science. For that reason we are including this debugging interlude. Debugging is a skill that you need to master over time, and some of the tips and tricks are specific to different aspects of Python programming.

Programming is an odd thing in a way. Here is why. As programmers we spend 99% of our time trying to get our program to work. We struggle, we stress, we spend hours deep in frustration trying to get our program to execute correctly. Then when we do get it going we celebrate, hand it in, and move on to the next homework assignment or programming task. But here is the secret, when you are successful, you are happy, your brain releases a bit of chemical that makes you feel good. You need to organize your programming so that you have lots of little successess. It turns out your brain doesn't care all that much if you have successfully written hello world, or a fast fourier transform (trust me its hard) you still get that little release that makes you happy. When you are happy you want to go on and solve the next little problem. Essentially I'm telling you once again, start small, get something small working, and then add to it.

diff --git a/pretext/Debugging/toctree.ptx b/pretext/Debugging/toctree.ptx index fafd30276..2f03e1bcc 100644 --- a/pretext/Debugging/toctree.ptx +++ b/pretext/Debugging/toctree.ptx @@ -1,10 +1,9 @@ -4Debugging Interlude 1 +4Debugging Interlude 4 4 4 4 4 -4 diff --git a/pretext/Files/Glossary.ptx b/pretext/Files/Glossary.ptx index a898e32ad..8cee89cbb 100644 --- a/pretext/Files/Glossary.ptx +++ b/pretext/Files/Glossary.ptx @@ -26,6 +26,26 @@ write

Will add characters to the end of a file that has been opened for writing.

+
+ + csv +

An optional Python module that provides useful functions for interacting with data in the Comma Separated Value format.

+
+ + Comma Separated Value +

A format that text files can have. Promises that the file contains alphanumeric values separate by single commas and organized into one row of data per line.

+
+ + reader +

A function part of the csv module that creates an object for traversing csv file data.

+
+ + writerow +

A function part of the csv module that takes a list of data, formats it in the appropriate csv format, and writes it to a data file.

+
+ + writerows +

A function part of the csv module. Similar to writerow, but can write multiple rows of data at once if given a list of lists.

absolute file path diff --git a/pretext/Files/ReadingCSV.ptx b/pretext/Files/ReadingCSV.ptx new file mode 100644 index 000000000..3a91fe72a --- /dev/null +++ b/pretext/Files/ReadingCSV.ptx @@ -0,0 +1,66 @@ + +
+ Reading Files as <c>csv</c> +

The climate change data file we have used as an example in this chapter has a more specific designation than just a .txt file. Because the file + consists of a series of values separated by commas, it can also be referred to as a Comma Separate Value file, or a .csv. Note that csv + files are still just text files, but knowing it is also a csv tells us something valuable about the structure of the data it contains. This makes it + easier to parse and interact with that data.

+ +

To interact with text files as csv's, we need to import the Python csv module and use it to create reader or writer objects. + This section focuses on reading csv, so we should use a reader. The reason we are interested in doing this is because the reader will automatically detect and remove + the commas separating values for us. Essentially, the reader will split the data up into lists for us. This makes it simpler to navigate and interact with the data in the file.

+

Let's see an example of this working.

+ + +import csv +with open("ccdata.csv", "r") as file: + csv_reader = csv.reader(file, delimiter=',') + for line in csv_reader: + print(line) + print(line[0]) # just years + + + +

Note that the value assigned to for loop line variable is a list rather than a single string like we would get with a standard file object. This allows us to acces column + data quickly with a single index value.

+ +

The following table describes the two csv functions you are most likely to want to use.

+ + + + + Method Name + + + Use + + + Explanation + + + + + reader + + + csv.reader(file_object) + + + Creates a csv reader object that automatically splits lines of data but can be looped through like a regular file object. + + + + + writer + + + csv.writer(file_object) + + + Creates a csv writer object that takes lists of strings and writes them to the provided file in the correct csv format. + + + +
+
diff --git a/pretext/Files/WritingCSV.ptx b/pretext/Files/WritingCSV.ptx new file mode 100644 index 000000000..ee265ce73 --- /dev/null +++ b/pretext/Files/WritingCSV.ptx @@ -0,0 +1,44 @@ + +
+ Writing Files as <c>csv</c> +

We already introduced the csv module in the previous section. Let's examine some examples using a csv.writer object.

+

Like the reader object, the csv.writer function takes a opened file object. Once set up, the csv file can be written to with writerow. + Make note that writerow does not need an explicit newline character \n to know when to end a line of text. This sets it apart for the the regular file.write() function.

+ + +import csv +data = [["Column_1_Name","Column_2_Name","Column_3_Name"], + [1,2,3], + [50,40,23] +] + +with open("new_file.csv", "w", newline='') as file: + csv_writer = csv.writer(file, delimiter=',') + for line in data: + csv_writer.writerow(line) + + +

This program will create a file called new_file.csv with the contents:

+
Column_1_Name,Column_2_Name,Column_3_Name
+1,2,3
+50,40,23
+

You may have noticed there is one new piece of code in our with open(... line. The newline='' parameter is needed here to avoid adding extra blank lines to our output file. + Try running this code locally without that part to see the difference.

+ +

There is one other writer method you may find useful, which is writerows. This allows you to write multiple rows of data at the same time. When applied to the previous + example, it saves us from having to set up a loop.

+ + +import csv + +data = [["Column_1_Name","Column_2_Name","Column_3_Name"], + [1,2,3], + [50,40,23] +] + +with open("new_file.csv", "w", newline='') as file: + csv_writer = csv.writer(file, delimiter=',') + csv_writer.writerows(data) + + +
diff --git a/pretext/Files/intro-WorkingwithDataFiles.ptx b/pretext/Files/intro-WorkingwithDataFiles.ptx index ab952e8a3..9fa57818f 100644 --- a/pretext/Files/intro-WorkingwithDataFiles.ptx +++ b/pretext/Files/intro-WorkingwithDataFiles.ptx @@ -1,8 +1,8 @@
Working with Data Files -

So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life data reside in files.

-

For example, web pages, word processing documents, and all data that live in files. In this short chapter we will introduce the Python concepts necessary to use data from files in our programs.

+

So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life, data reside in files.

+

For example, web pages, word processing documents, and all data that live in files. In this chapter we will introduce the Python concepts necessary to use data from files in our programs.

For our purposes, we will assume that our data files are text files–that is, files filled with characters. The Python programs that you write are stored as text files. We can create these files in any of a number of ways. For example, we could use a text editor to type in and save the data. We could also download the data from a website and then save it in a file. Regardless of how the file is created, Python will allow us to manipulate the contents.

In Python, we must open files before we can use them and close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

diff --git a/pretext/Files/toctree.ptx b/pretext/Files/toctree.ptx index a65214c9b..afa1b9357 100644 --- a/pretext/Files/toctree.ptx +++ b/pretext/Files/toctree.ptx @@ -8,7 +8,7 @@ 4 4 4 -4 +4 +4 4 -4 diff --git a/pretext/Functions/Exercises.ptx b/pretext/Functions/Exercises.ptx index 8f9b97277..598405787 100644 --- a/pretext/Functions/Exercises.ptx +++ b/pretext/Functions/Exercises.ptx @@ -2,193 +2,12 @@ Exercises - -

Use the drawsquare function we wrote in this chapter in a program to draw - the image shown below. - Assume each side is 20 units. - (Hint: notice that the turtle has already moved away from the ending point of the last - square when the program ends.)

- -
- - - -import turtle - -def drawSquare(t, sz): - """Get turtle t to draw a square of sz side""" - - for i in range(4): - t.forward(sz) - t.left(90) - -wn = turtle.Screen() -wn.bgcolor("lightgreen") - -alex = turtle.Turtle() -alex.color("pink") - -drawSquare(alex,20) - -wn.exitonclick() - - - - - -import turtle - -def drawSquare(t, sz): - """Make turtle t draw a square of with side sz.""" - for i in range(4): - t.forward(sz) - t.left(90) - -wn = turtle.Screen() # Set up the window and its attributes -wn.bgcolor("lightgreen") - -alex = turtle.Turtle() # create alex -alex.color('hotpink') -alex.pensize(3) - -for i in range(5): - drawSquare(alex, 20) # Call the function to draw the square - alex.penup() - alex.forward(40) # move alex to the starting position for the next square - alex.pendown() - -wn.exitonclick() - - - -
- - -

Write a program to draw this. Assume the innermost square is 20 units per side, - and each successive square is 20 units bigger, per side, than the one inside it.

- -
- - - - - -
- - -

Write a non-fruitful function drawPoly(someturtle, somesides, somesize) which makes a turtle - draw a regular polygon. - When called with drawPoly(tess, 8, 50), it will draw a shape like this:

- -
- - - - - - - - -import turtle - -def drawPoly(t, num_sides, side_length): - for i in range(num_sides): - t.forward(side_length) - t.left(360/num_sides) - -wn = turtle.Screen() # Set up the window and its attributes -wn.bgcolor("lightgreen") - -tess = turtle.Turtle() -tess.color('hotpink') -tess.pensize(3) - -drawPoly(tess, 8, 50) - - - -
- - -

Draw this pretty pattern.

- -
- - - - - -
- - -

The two spirals in this picture differ only by the turn angle. Draw both.

- -
- - - - - - - - -import turtle - -def drawSpiral(t, angle): - ''' takes a turtle, t, and an angle in degrees ''' - length = 1 - for i in range(84): - t.forward(length) - t.right(angle) - length = length + 2 - - -wn = turtle.Screen() # Set up the window and its attributes -wn.bgcolor("lightgreen") - -guido = turtle.Turtle() # create guido -guido.color('blue') - -## draw the first spiral ## -# position guido -guido.penup() -guido.backward(110) -guido.pendown() - -# draw the spiral using a 90 degree turn angle -drawSpiral(guido, 90) - - -## draw the second spiral ## -# position guido -guido.home() -guido.penup() -guido.forward(90) -guido.pendown() - -drawSpiral(guido, 89) - - - -
- - -

Write a non-fruitful function drawEquitriangle(someturtle, somesize) which calls drawPoly from the - previous question to have its turtle draw a equilateral triangle.

-
- - - - - -
-

Write a fruitful function sumTo(n) that returns the sum of all integer numbers up to and including n. So sumTo(10) would be 1+2+3...+10 which would return the value 55. Use the equation (n * (n + 1)) / 2.

- + def sumTo(n): @@ -207,7 +26,7 @@ myTests().main() - + from test import testEqual @@ -226,11 +45,11 @@ print("The sum from 1 to 5 is",t)
- +

Write a function areaOfCircle(r) which returns the area of a circle of radius r. Make sure you use the math module in your solution.

- + def areaOfCircle(r): @@ -250,90 +69,12 @@ myTests().main()
- - -

Write a non-fruitful function to draw a five pointed star, where the length of each side is 100 units.

- -
- - - - - - - - -import turtle - -def drawFivePointStar(t): - for i in range(5): - t.forward(100) - t.left(216) - -wolfram = turtle.Turtle() -drawFivePointStar(wolfram) - - - -
- - -

Extend your program above. Draw five stars, but between each, pick up the pen, - move forward by 350 units, turn right by 144, put the pen down, and draw the next star. - You'll get something like this (note that you will need to move to the left before drawing your first star in order to fit everything in the window):

- -

What would it look like if you didn't pick up the pen?

-
- - - - - -
- - -

Extend the star function to draw an n pointed star. (Hint: n must be an odd number greater or - equal to 3).

-
- - - - - - - - -import turtle - -def drawStar(t, n): - for i in range(n): - t.forward(100) - t.left(180 - 180/n) - -stroustrup = turtle.Turtle() -drawStar(stroustrup, 7) - - - -
- - -

Write a function called drawSprite that will draw a sprite. The function will need parameters for - the turtle, the number of legs, and the length of the legs. Invoke the function to create a sprite - with 15 legs of length 120.

-
- - - - - -
- +

Rewrite the function sumTo(n) that returns the sum of all integer numbers up to and including n. This time use the accumulator pattern.

- + def sumTo(n): @@ -351,7 +92,7 @@ myTests().main() - + def sumTo(n): sum = 0 @@ -370,37 +111,12 @@ print("The sum from 1 to 5 is",t)
- - -

Write a function called mySqrt that will approximate the square root of a number, call it n, by using - Newton's algorithm. - Newton's approach is an iterative guessing algorithm where the initial guess is n/2 and each subsequent guess - is computed using the formula: newguess = (1/2) * (oldguess + (n/oldguess)).

-
- - - -def mySqrt(n): - # your code here ==== -from unittest.gui import TestCaseGui - -class myTests(TestCaseGui): - def testOne(self): - self.assertAlmostEqual(mySqrt(4.0),2.0,0,"Tested mySqrt on input 4.0") - self.assertAlmostEqual(mySqrt(9.0),3.0,4,"Tested accuracy of mySqrt on input 3.0") - self.assertAlmostEqual(mySqrt(36.0),6.0,5,"Tested accuracy of mySqrt on input 6.0") - self.assertAlmostEqual(mySqrt(100.0),10.0,4,"Tested accuracy of mySqrt on input 10.0. Try iterating more times.") - -myTests().main() - - -
- +

Write a function called myPi that will return an approximation of PI (3.14159…). Use the Leibniz approximation.

- + def myPi(iters): @@ -411,7 +127,7 @@ myTests().main() - + def myPi(iters): ''' Calculate an approximation of PI using the Leibniz @@ -433,12 +149,12 @@ print(pi_approx)
- +

Write a function called myPi that will return an approximation of PI (3.14159…). Use the Madhava approximation.

- + def myPi(iters): @@ -449,92 +165,4 @@ def myPi(iters):
- - -

Write a function called fancySquare that will draw a square with fancy corners (sprites on the corners). You should - implement and use the drawSprite function from above. For an even more interesting look, how about adding small - triangles to the ends of the sprite legs.

-
- - - - - - - - -import turtle - -def drawSprite(t, numlegs, leglength): - angle = 360/numlegs - for i in range(numlegs): - t.forward(leglength) - t.backward(leglength) - t.left(angle) - -def drawFancySquare(t, sz, lgs, lgl): - for i in range(4): - t.forward(sz) - drawSprite(t, lgs, lgl) - t.left(90) - -wn = turtle.Screen() -wn.bgcolor("lightgreen") - -alex = turtle.Turtle() -drawFancySquare(alex, 100, 10, 15) - -wn.exitonclick() - - - -
- - -

There was a whole program in to create a bar chart with specific data. Creating a bar chart is a useful idea in general. Write a non-fruitful function called barChart, that takes the numeric list of data as a parameter, and draws the bar chart. Write a full program calling this function. - The current version of the drawBar function unfortuately draws the top of the bar through the bottom of the label. A nice elaboration is to make the label appear completely above the top line. To keep the spacing consistent you might pass an extra parameter to drawBar for the distance to move up. For the barChart function make that parameter be some small fraction of maxheight+border. The fill action makes this modification particularly tricky: You will want to move past the top of the bar and write before or after drawing and filling the bar.

-
- - - -import turtle - -def drawBar(t, height): - """ Get turtle t to draw one bar, of height. """ - t.begin_fill() # start filling this shape - t.left(90) - t.forward(height) - t.write(str(height)) - t.right(90) - t.forward(40) - t.right(90) - t.forward(height) - t.left(90) - t.end_fill() # stop filling this shape - - - -xs = [48, 117, 200, 240, 160, 260, 220] # here is the data -maxheight = max(xs) -numbars = len(xs) -border = 10 - -wn = turtle.Screen() # Set up the window and its attributes -wn.setworldcoordinates(0-border, 0-border, 40*numbars+border, maxheight+border) -wn.bgcolor("lightgreen") - -tess = turtle.Turtle() # create tess and set some attributes -tess.color("blue") -tess.fillcolor("red") -tess.pensize(3) - - - -for a in xs: - drawBar(tess, a) - -wn.exitonclick() - - -
diff --git a/pretext/Functions/TheAccumulatorPattern.ptx b/pretext/Functions/TheAccumulatorPattern.ptx index f875e2b51..4cf6f9576 100644 --- a/pretext/Functions/TheAccumulatorPattern.ptx +++ b/pretext/Functions/TheAccumulatorPattern.ptx @@ -2,7 +2,7 @@
The Accumulator Pattern -
@@ -145,135 +145,13 @@

The square and round brackets denote closed and open intervals. A closed interval includes the number, and open interval excludes it. So 79.99999 gets grade C , but 80 gets grade B.

-

Test your function by printing the mark and the grade for a number of different marks.

+

Test your code by printing the mark and the grade for a number of different marks.

- - -def getGrade(grade): - #your code here - - -==== - -from unittest.gui import TestCaseGui - -class myTests(TestCaseGui): - - def testOne(self): - self.assertEqual(getGrade(95),'A','Tested getGrade on input of 95') - self.assertEqual(getGrade(85),'B','Tested getGrade on input of 85') - self.assertEqual(getGrade(65),'D','Tested getGrade on input of 65') - self.assertEqual(getGrade(79.99999),'C','Tested getGrade on input of 79.9999') - self.assertEqual(getGrade(80),'B','Tested getGrade on input of 80') - - -myTests().main() - - - - - -def grade(mark): - if mark >= 90: - return "A" - else: - if mark >= 80: - return "B" - else: - if mark >= 70: - return "C" - else: - if mark >= 60: - return "D" - else: - return "F" - -mark = 83 -print( "Mark:", str(mark), "Grade:", grade(mark)) - - - - - - -

Modify the turtle bar chart program from the previous chapter so that the bar for any value - of 200 or more is filled with red, values between [100 and 200) are filled yellow, - and bars representing values less than 100 are filled green.

-
- - - - - -
- - -

In the turtle bar chart program, what do you expect to happen if one or more - of the data values in the list is negative? Go back and try it out. Change the - program so that when it prints the text value for the negative bars, it puts - the text above the base of the bar (on the 0 axis).

-
- - - - - - - - -import turtle - -def drawBar(t, height): - """ Get turtle t to draw one bar, of height. """ - t.begin_fill() # start filling this shape - if height < 0: - t.write(str(height)) - t.left(90) - t.forward(height) - if height >= 0: - t.write(str(height)) - t.right(90) - t.forward(40) - t.right(90) - t.forward(height) - t.left(90) - t.end_fill() # stop filling this shape - - - -xs = [48, -50, 200, 240, 160, 260, 220] # here is the data -maxheight = max(xs) -minheight = min(xs) -numbars = len(xs) -border = 10 - -tess = turtle.Turtle() # create tess and set some attributes -tess.color("blue") -tess.fillcolor("red") -tess.pensize(3) - -wn = turtle.Screen() # Set up the window and its attributes -wn.bgcolor("lightgreen") -if minheight > 0: - lly = 0 -else: - lly = minheight - border - -wn.setworldcoordinates(0-border, lly, 40*numbars+border, maxheight+border) - - -for a in xs: - drawBar(tess, a) - -wn.exitonclick() - - -
-

Write a function findHypot. The function will be given the length of two sides of a right-angled triangle and it should return - the length of the hypotenuse. (Hint: x ** 0.5 will return the square root, or use sqrt from the math module)

+

Write code that will calculate the length of the hypotenuse function will be given the length of two sides of a right-angled triangle and it should return + the . (Hint: x ** 0.5 will return the square root, or use sqrt from the math module)

@@ -298,48 +176,13 @@ myTests().main()
-

Write a function called is_even(n) that takes an integer as an argument - and returns True if the argument is an even number and False if +

Write code that takes an integer and prints True if the integer is an even number and False if it is odd.

- - -def is_even(n): - # your code here - -==== - -from unittest.gui import TestCaseGui - -class myTests(TestCaseGui): - def testOne(self): - self.assertEqual(is_even(10),True,"Tested is_even on input of 10") - self.assertEqual(is_even(5),False,"Tested is_even on input of 5") - self.assertEqual(is_even(1),False,"Tested is_even on input of 1") - self.assertEqual(is_even(0),True,"Tested is_even on input of 0") - -myTests().main() + # your code here - - - -from test import testEqual - -def is_even(n): - if n % 2 == 0: - return True - else: - return False - -testEqual(is_even(10), True) -testEqual(is_even(5), False) -testEqual(is_even(1), False) -testEqual(is_even(0), True) - - -
diff --git a/pretext/Selection/toctree.ptx b/pretext/Selection/toctree.ptx index 57bde1c71..380b0ade8 100644 --- a/pretext/Selection/toctree.ptx +++ b/pretext/Selection/toctree.ptx @@ -12,5 +12,4 @@ 4 4 4 -4 diff --git a/pretext/SimplePythonData/toctree.ptx b/pretext/SimplePythonData/toctree.ptx index 74d9ecdd6..7eb94a591 100644 --- a/pretext/SimplePythonData/toctree.ptx +++ b/pretext/SimplePythonData/toctree.ptx @@ -13,5 +13,4 @@ 4 4 4 -4 diff --git a/pretext/Strings/toctree.ptx b/pretext/Strings/toctree.ptx index 2e60eed65..d9088bc14 100644 --- a/pretext/Strings/toctree.ptx +++ b/pretext/Strings/toctree.ptx @@ -13,5 +13,4 @@ 4 4 4 -4 diff --git a/pretext/thinkcspy.ptx b/pretext/thinkcspy.ptx index 7ab3c1a5f..ffbb4e2c1 100644 --- a/pretext/thinkcspy.ptx +++ b/pretext/thinkcspy.ptx @@ -20,11 +20,11 @@ - + - + From 9302e195f92b980a614f6a3f8d3e60b4f652a79f Mon Sep 17 00:00:00 2001 From: robotuw Date: Fri, 16 Jun 2023 11:09:20 -0600 Subject: [PATCH 34/90] Overhaul Complete Large number of changes to chapter organization and activity numbering. --- .../AdditionalTopics/ListComprehensions.ptx | 8 ++-- .../AddingOtherMethodstoourClass.ptx | 4 +- .../ConvertinganObjecttoaString.ptx | 4 +- .../ClassesBasics/ImprovingourConstructor.ptx | 2 +- .../ClassesBasics/InstancesasReturnValues.ptx | 4 +- pretext/ClassesBasics/ObjectsRevisited.ptx | 2 +- .../ObjectsasArgumentsandParameters.ptx | 2 +- pretext/ClassesBasics/UserDefinedClasses.ptx | 12 +++--- pretext/ClassesBasics/toctree.ptx | 1 - .../ArithmeticMethods.ptx | 4 +- pretext/ClassesDiggingDeeper/Fractions.ptx | 2 +- .../ObjectsareMutable.ptx | 4 +- pretext/ClassesDiggingDeeper/Sameness.ptx | 4 +- pretext/ClassesDiggingDeeper/toctree.ptx | 1 - pretext/ComplexLogic/Afindfunction.ptx | 4 +- .../ComplexLogic/NestedList_Navigation.ptx | 12 +++--- pretext/ComplexLogic/NestedLists.ptx | 8 ++-- pretext/ComplexLogic/ObjectsandReferences.ptx | 8 ++-- pretext/ComplexLogic/PureFunctions.ptx | 6 +-- .../TheAccumulatorPatternwithLists.ptx | 42 +++++++++---------- .../TheAccumulatorPatternwithStrings.ptx | 10 ++--- .../ComplexLogic/UsingListsasParameters.ptx | 6 +-- pretext/ComplexLogic/toctree.ptx | 5 +-- pretext/Debugging/HowtoAvoidDebugging.ptx | 10 ++--- pretext/Debugging/KnowyourerrorMessages.ptx | 14 +++---- .../Files/AlternativeFileReadingMethods.ptx | 2 +- pretext/Files/Iteratingoverlinesinafile.ptx | 2 +- pretext/Files/ReadingCSV.ptx | 2 +- pretext/Files/WithStatements.ptx | 2 +- pretext/Files/WritingCSV.ptx | 4 +- pretext/Files/WritingTextFiles.ptx | 4 +- pretext/Functions/BooleanFunctions.ptx | 18 ++++---- pretext/Functions/Composition.ptx | 2 +- pretext/Functions/FlowofExecutionSummary.ptx | 4 +- .../Functionscancallotherfunctions.ptx | 2 +- .../Functions/Functionsthatreturnvalues.ptx | 16 +++---- pretext/Functions/ProgramDevelopment.ptx | 4 +- pretext/Functions/TheAccumulatorPattern.ptx | 10 ++--- pretext/Functions/UnitTesting.ptx | 10 ++--- .../Variablesandparametersarelocal.ptx | 14 +++---- pretext/Functions/functions.ptx | 20 ++++----- pretext/Functions/mainfunction.ptx | 4 +- pretext/GeneralIntro/ATypicalFirstProgram.ptx | 4 +- pretext/GeneralIntro/Algorithms.ptx | 4 +- pretext/GeneralIntro/Comments.ptx | 4 +- .../GeneralIntro/ExperimentalDebugging.ptx | 2 +- .../FormalandNaturalLanguages.ptx | 4 +- pretext/GeneralIntro/MoreAboutPrograms.ptx | 2 +- pretext/GeneralIntro/RuntimeErrors.ptx | 4 +- pretext/GeneralIntro/SemanticErrors.ptx | 4 +- .../SpecialWaystoExecutePythoninthisBook.ptx | 8 ++-- pretext/GeneralIntro/Syntaxerrors.ptx | 4 +- .../ThePythonProgrammingLanguage.ptx | 6 +-- pretext/GeneralIntro/WhatisDebugging.ptx | 2 +- .../CalculatingtheSumofaListofNumbers.ptx | 4 +- .../ConvertinganIntegertoaStringinAnyBase.ptx | 6 +-- .../TheThreeLawsofRecursion.ptx | 4 +- pretext/Iteration/BreakAndContinue.ptx | 6 +-- .../FlowofExecutionofthewhileLoop.ptx | 4 +- pretext/Iteration/Glossary.ptx | 5 +++ pretext/Iteration/Listsandforloops.ptx | 14 +++---- .../Iteration/SentinelValuesAndValidation.ptx | 12 +++--- pretext/Iteration/The3n1Sequence.ptx | 8 ++-- pretext/Iteration/TheforLoop.ptx | 6 +-- pretext/Iteration/TherangeFunction.ptx | 20 ++++----- pretext/Iteration/ThewhileStatement.ptx | 16 +++---- .../TraversalandtheforLoopByIndex.ptx | 10 ++--- .../TraversalandtheforLoopByItem.ptx | 12 +++--- .../Iteration/TraversalandthewhileLoop.ptx | 10 ++--- pretext/Iteration/intro-Iteration.ptx | 4 +- pretext/Lists/AccessingElements.ptx | 8 ++-- pretext/Lists/AppendversusConcatenate.ptx | 8 ++-- pretext/Lists/CloningLists.ptx | 2 +- pretext/Lists/ConcatenationandRepetition.ptx | 8 ++-- pretext/Lists/ListDeletion.ptx | 4 +- pretext/Lists/ListLength.ptx | 6 +-- pretext/Lists/ListMethods.ptx | 14 +++---- pretext/Lists/ListSlices.ptx | 8 ++-- pretext/Lists/ListValues.ptx | 4 +- pretext/Lists/ListsareMutable.ptx | 12 +++--- pretext/Lists/StringsandLists.ptx | 8 ++-- pretext/Lists/listTypeConversionFunction.ptx | 2 +- pretext/PythonModules/CreatingModules.ptx | 6 +-- pretext/PythonModules/Therandommodule.ptx | 18 ++++---- pretext/PythonModules/modules.ptx | 8 ++-- .../BooleanValuesandBooleanExpressions.ptx | 8 ++-- pretext/Selection/Chainedconditionals.ptx | 6 +-- .../ConditionalExecutionBinarySelection.ptx | 8 ++-- pretext/Selection/ListMembership.ptx | 8 ++-- pretext/Selection/Logicaloperators.ptx | 10 ++--- pretext/Selection/Nestedconditionals.ptx | 6 +-- .../OmittingtheelseClauseUnarySelection.ptx | 6 +-- pretext/Selection/PrecedenceofOperators.ptx | 4 +- pretext/Selection/StringComparison.ptx | 18 ++++---- pretext/Selection/Theinandnotinoperators.ptx | 8 ++-- pretext/SimplePythonData/Input.ptx | 12 +++--- .../SimplePythonData/OperatorsandOperands.ptx | 16 +++---- .../SimplePythonData/OrderofOperations.ptx | 8 ++-- pretext/SimplePythonData/Reassignment.ptx | 8 ++-- .../StatementsandExpressions.ptx | 6 +-- .../Typeconversionfunctions.ptx | 8 ++-- .../SimplePythonData/UpdatingVariables.ptx | 10 ++--- .../SimplePythonData/ValuesandDataTypes.ptx | 22 +++++----- .../VariableNamesandKeywords.ptx | 2 +- pretext/SimplePythonData/Variables.ptx | 12 +++--- pretext/Strings/Characterclassification.ptx | 4 +- pretext/Strings/Glossary.ptx | 5 --- ...ratorWorkingwiththeCharactersofaString.ptx | 6 +-- pretext/Strings/Length.ptx | 12 +++--- pretext/Strings/OperationsonStrings.ptx | 8 ++-- pretext/Strings/StringMethods.ptx | 10 ++--- pretext/Strings/StringsareImmutable.ptx | 6 +-- pretext/Strings/Summary.ptx | 8 ++-- pretext/Strings/TheSliceOperator.ptx | 10 ++--- pretext/Strings/fStrings.ptx | 12 +++--- 115 files changed, 433 insertions(+), 438 deletions(-) diff --git a/pretext/AdditionalTopics/ListComprehensions.ptx b/pretext/AdditionalTopics/ListComprehensions.ptx index f2ac50d45..601376f29 100644 --- a/pretext/AdditionalTopics/ListComprehensions.ptx +++ b/pretext/AdditionalTopics/ListComprehensions.ptx @@ -1,10 +1,10 @@ -
+
List Comprehensions

The previous example creates a list from a sequence of values based on some selection criteria. An easy way to do this type of processing in Python is to use a list comprehension. List comprehensions are concise ways to create lists. The general syntax is:

[<expression> for <item> in <sequence> if  <condition>]

where the if clause is optional. For example,

- + mylist = [1,2,3,4,5] @@ -26,7 +26,7 @@ def primes_upto(n):

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -36,7 +36,7 @@ def primes_upto(n):

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx b/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx index 5efd49969..c4d897295 100644 --- a/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx +++ b/pretext/ClassesBasics/AddingOtherMethodstoourClass.ptx @@ -14,7 +14,7 @@ append method and add the integer 90 to the end of the list. Methods are accessed using dot notation.

Let's add two simple methods to allow a point to give us information about its state. The getX method, when invoked, will return the value of the x coordinate. The implementation of this method is straight forward since we already know how to write functions that return values. One thing to notice is that even though the getX method does not need any other parameter information to do its work, there is still one formal parameter, self. As we stated earlier, all methods defined in a class that operate on objects of that class will have self as their first parameter. Again, this serves as reference to the object itself which in turn gives access to the state data inside the object.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ @@ -40,7 +40,7 @@ print(p.getY())

Let's add another method, distanceFromOrigin, to see better how methods work. This method will again not need any additional information to do its work. It will perform a more complex task.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ diff --git a/pretext/ClassesBasics/ConvertinganObjecttoaString.ptx b/pretext/ClassesBasics/ConvertinganObjecttoaString.ptx index d46f2cc7a..c213d5d0d 100644 --- a/pretext/ClassesBasics/ConvertinganObjecttoaString.ptx +++ b/pretext/ClassesBasics/ConvertinganObjecttoaString.ptx @@ -3,7 +3,7 @@ Converting an Object to a String

When we're working with classes and objects, it is often necessary to print an object (that is to print the state of an object). Consider the example below.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ @@ -35,7 +35,7 @@ print(p)

The __str__ method is responsible for returning a string representation as defined by the class creator. In other words, you as the programmer, get to choose what a Point should look like when it gets printed. In this case, we have decided that the string representation will include the values of x and y as well as some identifying text. It is required that the __str__ method create and return a string.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ diff --git a/pretext/ClassesBasics/ImprovingourConstructor.ptx b/pretext/ClassesBasics/ImprovingourConstructor.ptx index e4fc90bde..977f74f60 100644 --- a/pretext/ClassesBasics/ImprovingourConstructor.ptx +++ b/pretext/ClassesBasics/ImprovingourConstructor.ptx @@ -5,7 +5,7 @@ provide some additional capability for the user to pass information to the constructor. Since constructors are simply specially named functions, we can use parameters (as we've seen before) to provide the specific information.

We can make our class constructor more general by putting extra parameters into the __init__ method, as shown in this codelens example.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ diff --git a/pretext/ClassesBasics/InstancesasReturnValues.ptx b/pretext/ClassesBasics/InstancesasReturnValues.ptx index c246aeadf..71ca70edf 100644 --- a/pretext/ClassesBasics/InstancesasReturnValues.ptx +++ b/pretext/ClassesBasics/InstancesasReturnValues.ptx @@ -8,7 +8,7 @@ and wish to find the midpoint halfway between it and some other target point. We would like to write a method, call it halfway that takes another Point as a parameter and returns the Point that is halfway between the point and the target.

- + class Point: @@ -50,7 +50,7 @@ print(mid.getY()) We can always see whether the coordinates of Point self or target are being referred to.

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/ClassesBasics/ObjectsRevisited.ptx b/pretext/ClassesBasics/ObjectsRevisited.ptx index a15cb0817..bc12ff29b 100644 --- a/pretext/ClassesBasics/ObjectsRevisited.ptx +++ b/pretext/ClassesBasics/ObjectsRevisited.ptx @@ -7,5 +7,5 @@ that the object knows about itself. For example, each list has a state consisting of the items it contains, a length and so on. Each list also has the ability to add, delete, and sort the items inside of it. Individual lists are different in that even though they are all lists, they differ in the specific values of the individual state attributes (maybe they have different items inside them).

- Simple object has state and methods +
diff --git a/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx b/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx index 58067f71f..7be61958f 100644 --- a/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx +++ b/pretext/ClassesBasics/ObjectsasArgumentsandParameters.ptx @@ -3,7 +3,7 @@ Objects as Arguments and Parameters

You can pass an object as an argument in the usual way. Here is a simple function called distance involving our new Point objects. The job of this function is to figure out the distance between two points.

- + import math diff --git a/pretext/ClassesBasics/UserDefinedClasses.ptx b/pretext/ClassesBasics/UserDefinedClasses.ptx index f0cf67485..757165bb2 100644 --- a/pretext/ClassesBasics/UserDefinedClasses.ptx +++ b/pretext/ClassesBasics/UserDefinedClasses.ptx @@ -49,7 +49,7 @@ class Point: other name, but nobody ever does!) is automatically set to reference the newly-created object that needs to be initialized.

So let's use our new Point class now.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ @@ -77,7 +77,7 @@ print("Nothing seems to have happened with the points") having an x and y coordinate with value 0. However, because we have not asked the point to do anything, we don't see any other result.

Simple object has state and methods

You can see this for yourself, via codelens:

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ @@ -95,7 +95,7 @@ print("Nothing seems to have happened with the points")

The following program adds a few print statements. You can see that the output suggests that each one is a Point object. However, notice that the is operator returns False meaning that they are different objects (we will have more to say about this in a later chapter).

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ @@ -114,7 +114,7 @@ print(q) print(p is q) -

This should look familiar — we've used classes before to create +

The variables p and q are assigned references to two new Point objects. A function like Turtle or Point that creates a new object instance is called a constructor. Every class automatically uses the name of the class as the name of the constructor function. @@ -141,7 +141,7 @@ alex = Turtle()

Check Your Understanding

- +

What is the the output of the following print code?

diff --git a/pretext/ClassesBasics/toctree.ptx b/pretext/ClassesBasics/toctree.ptx index 4d9669ccf..245c14591 100644 --- a/pretext/ClassesBasics/toctree.ptx +++ b/pretext/ClassesBasics/toctree.ptx @@ -11,5 +11,4 @@ 4 4 4 -4 diff --git a/pretext/ClassesDiggingDeeper/ArithmeticMethods.ptx b/pretext/ClassesDiggingDeeper/ArithmeticMethods.ptx index 62e988b93..f98e63ca2 100644 --- a/pretext/ClassesDiggingDeeper/ArithmeticMethods.ptx +++ b/pretext/ClassesDiggingDeeper/ArithmeticMethods.ptx @@ -23,7 +23,7 @@ def add(self,otherfraction):

You can try the addition method and then modify the fractions and retry.

- + def gcd(m, n): while m % n != 0: @@ -94,7 +94,7 @@ print(f3)

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/ClassesDiggingDeeper/Fractions.ptx b/pretext/ClassesDiggingDeeper/Fractions.ptx index 879380f0f..8c89a58b2 100644 --- a/pretext/ClassesDiggingDeeper/Fractions.ptx +++ b/pretext/ClassesDiggingDeeper/Fractions.ptx @@ -12,7 +12,7 @@

To design our class, we simply need to use the analysis above to realize that the state of a fraction object can be completely described by representing two integers. We can begin by implementing the Fraction class and the __init__ method which will allow the user to provide a numerator and a denominator for the fraction being created.

- + class Fraction: diff --git a/pretext/ClassesDiggingDeeper/ObjectsareMutable.ptx b/pretext/ClassesDiggingDeeper/ObjectsareMutable.ptx index 21fd86124..7b170476b 100644 --- a/pretext/ClassesDiggingDeeper/ObjectsareMutable.ptx +++ b/pretext/ClassesDiggingDeeper/ObjectsareMutable.ptx @@ -12,7 +12,7 @@ representation would be 3/4.

There is a very nice iterative method for computing the greatest common divisor of two integers. Try to run the function on a number of different examples.

- + def gcd(m, n): while m % n != 0: @@ -31,7 +31,7 @@ print(gcd(12, 16)) a fraction method called simplify. We will ask the fraction to put itself in lowest terms.

The simplify method will pass the numerator and the denominator to the gcd function to find the greatest common divisor. It will then modify itself by dividing its num and its den by that value.

- + def gcd(m, n): while m % n != 0: diff --git a/pretext/ClassesDiggingDeeper/Sameness.ptx b/pretext/ClassesDiggingDeeper/Sameness.ptx index a6768f6d8..1dd7ac238 100644 --- a/pretext/ClassesDiggingDeeper/Sameness.ptx +++ b/pretext/ClassesDiggingDeeper/Sameness.ptx @@ -13,7 +13,7 @@

We've already seen the is operator in the chapter on lists, where we talked about aliases. It allows us to find out if two references refer to the same object.

- + class Fraction: @@ -53,7 +53,7 @@ def sameRational(f1, f2):

This type of equality is known as deep equality since it compares the values deep in the object, not just the reference to the object.

- + def sameRational(f1, f2): return f1.getNum()*f2.getDen() == f2.getNum() * f1.getDen() diff --git a/pretext/ClassesDiggingDeeper/toctree.ptx b/pretext/ClassesDiggingDeeper/toctree.ptx index 83d49f7dc..32970d8df 100644 --- a/pretext/ClassesDiggingDeeper/toctree.ptx +++ b/pretext/ClassesDiggingDeeper/toctree.ptx @@ -6,5 +6,4 @@ 4 4 4 -4 diff --git a/pretext/ComplexLogic/Afindfunction.ptx b/pretext/ComplexLogic/Afindfunction.ptx index c531bb891..723b13c40 100644 --- a/pretext/ComplexLogic/Afindfunction.ptx +++ b/pretext/ComplexLogic/Afindfunction.ptx @@ -1,8 +1,8 @@ -
+
A <c>find</c> function

Here is an implementation for a restricted find method, where the target is a single character.

- + def find(astring, achar): """ diff --git a/pretext/ComplexLogic/NestedList_Navigation.ptx b/pretext/ComplexLogic/NestedList_Navigation.ptx index 96184c757..5ece66b89 100644 --- a/pretext/ComplexLogic/NestedList_Navigation.ptx +++ b/pretext/ComplexLogic/NestedList_Navigation.ptx @@ -7,7 +7,7 @@

The following program concerns a list of lists of names. In some cases, we may want to take nested list data and "un-nest" it. To do this, we need to iterate through the outer list, and then construct another loop to iterate through each name in each sublist. In this program's case, we are simply printing each name as we encounter it.

- + names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] for sublist in names: @@ -17,7 +17,7 @@ for sublist in names:

Nested lists can also be navigated by index rather than by value. This complicates the code somewhat, but gives us more flexibility for what can be done to each item. In this example program, we visit each name and turn it lowercase.

- + names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] for sublist_index in range(len(names)): @@ -29,7 +29,7 @@ print(names)

Note that in the above program it is very important that we use len(names[sublist_index]) in the second range call. Because the nested lists in this example do not have the same length, we have to check the length of each sublist when setting up our nested for loop bounds. If we do not do this carefully, then we can easily miss data or get an out of bounds exception. Consider a different, erroneous example:

- + names = [["Thomas", "Abraham", "George"], ["Theodore", "Grover", "William"], ["Franklin", "Dwight", "John", "Harry"], ["George", "Bill"]] for sublist_index in range(len(names)): @@ -41,7 +41,7 @@ print(names)

Nested lists can be used in many different contexts, but one more common use is to model 2D grids of data. Here is one last example that treats nested lists as a 2D coordinate plane and finds the location of a single value in that plane. Note this example reverses the y axis, so y values increase as you travel downward. This is to match the indexing on the lists, though we could model this as a more familiar coordinate system with some small changes.

- + coord = [['_', '_', '_', '_'], ['_', '_', 'p', '_'], @@ -53,10 +53,10 @@ for y in range(len(names)): print(f'p is as coordinates (x={x}, y={y})') -

+

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/ComplexLogic/NestedLists.ptx b/pretext/ComplexLogic/NestedLists.ptx index 04ea9df74..0e5b5cf9e 100644 --- a/pretext/ComplexLogic/NestedLists.ptx +++ b/pretext/ComplexLogic/NestedLists.ptx @@ -1,5 +1,5 @@ -
+
Nested Lists

A nested list is a list that appears as an element in another list. In this list, the element with index 3 is a nested list. @@ -7,7 +7,7 @@ nested list, we can proceed in two steps. First, extract the nested list, then extract the item of interest. It is also possible to combine those steps using bracket operators that evaluate from left to right.

- + nested = ["hello", 2.0, 5, [10, 20]] innerlist = nested[3] @@ -18,10 +18,10 @@ print(item) print(nested[3][1]) -

+

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/ComplexLogic/ObjectsandReferences.ptx b/pretext/ComplexLogic/ObjectsandReferences.ptx index bf8bd24d2..d055a62f9 100644 --- a/pretext/ComplexLogic/ObjectsandReferences.ptx +++ b/pretext/ComplexLogic/ObjectsandReferences.ptx @@ -1,5 +1,5 @@ -
+
Objects and References

If we execute these assignment statements,

@@ -19,7 +19,7 @@ b = "banana" refer to.

We already know that objects can be identified using their unique identifier. We can also test whether two names refer to the same object using the is operator. The is operator will return true if the two references are to the same object. In other words, the references are the same. Try our example from above.

- + a = "banana" b = "banana" @@ -32,7 +32,7 @@ print(a is b) Since strings are immutable, Python can optimize resources by making two names that refer to the same string literal value refer to the same object.

This is not the case with lists. Consider the following example. Here, a and b refer to two different lists, each of which happens to have the same element values.

- + a = [81, 82, 83] b = [81, 82, 83] @@ -48,7 +48,7 @@ print(a == b) a and b have the same value but do not refer to the same object.

There is one other important thing to notice about this reference diagram. The variable a is a reference to a collection of references. Those references actually refer to the integer values in the list. In other words, a list is a collection of references to objects. Interestingly, even though a and b are two different lists (two different collections of references), the integer object 81 is shared by both. Like strings, integers are also immutable so Python optimizes and lets everyone share the same object for some commonly used small integers.

Here is the example in codelens. Pay particular attention to the id values.

- + a = [81, 82, 83] b = [81, 82, 83] diff --git a/pretext/ComplexLogic/PureFunctions.ptx b/pretext/ComplexLogic/PureFunctions.ptx index 453bf9383..f116f181a 100644 --- a/pretext/ComplexLogic/PureFunctions.ptx +++ b/pretext/ComplexLogic/PureFunctions.ptx @@ -1,5 +1,5 @@ -
+
Pure Functions

A pure function does not produce side effects. It communicates with the calling program only through parameters (which it does not modify) and a return @@ -7,7 +7,7 @@ To use the pure function version of double_stuff to modify things, you would assign the return value back to things.

- + def doubleStuff(a_list): """ Return a new list in which contains doubles of the elements in a_list. """ @@ -24,7 +24,7 @@ print(things)

Once again, codelens helps us to see the actual references and objects as they are passed and returned.

- + def doubleStuff(a_list): """ Return a new list in which contains doubles of the elements in a_list. """ diff --git a/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx index 17462b8a3..b96ff174c 100644 --- a/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx +++ b/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx @@ -1,5 +1,5 @@ -
+
The Accumulator Pattern with Lists

Remember the ? Many algorithms involving lists make use of @@ -7,23 +7,23 @@ explore the use of the accumulator pattern with lists.

Let's take the problem of adding up all of the items in a list. The following program computes the sum of a list of numbers.

- + -sum = 0 +total = 0 for num in [1, 3, 5, 7, 9]: - sum = sum + num -print(sum) + total = total + num +print(total) -

The program begins by defining an accumulator variable, sum, and initializing it to 0 (line 1).

+

The program begins by defining an accumulator variable, total, and initializing it to 0 (line 1).

Next, the program iterates over the list (lines 2-3), and updates the sum on each - iteration by adding an item from the list (line 3). When the loop is finished, sum + iteration by adding an item from the list (line 3). When the loop is finished, total has accumulated the sum of all of the items in the list.

Take a moment to step through this program using CodeLens to see how it works. It's important to grasp the basic techniques.

Sometimes when we're accumulating, we don't want to add to our accumulator every time we iterate. Consider, for example, the following program which counts the number of names with more than 3 letters.

- + long_names = 0 for name in ["Joe", "Sally", "Amy", "Brad"]: @@ -39,7 +39,7 @@ print(long_names) it.

At the end, we have accumulated the total number of long names.

We can use conditionals to also count if particular items are in a string or list. The following code finds all occurrences of vowels in a string.

- + s = "what if we went to the zoo" num_vowels = 0 @@ -53,13 +53,13 @@ print(num_vowels) an o. If it is an o then we will update our counter.

a gif that shows code to check that "o" is in the phrase "onomatopoeia".
- + Accumulating the Max Value

We can also use the accumulation pattern with conditionals to find the maximum or minimum value. Instead of continuing to build up the accumulator value like we have when counting or finding a sum, we can reassign the accumulator variable to a different value.

The following example shows how we can get the maximum value from a list of integers.

- + nums = [9, 3, 8, 11, 5, 29, 2] best_num = 0 @@ -77,7 +77,7 @@ print(best_num) happen to our code? What if we were looking for the smallest number but we initialized best_num with zero? To get around this issue, we can initialize the accumulator variable using one of the numbers in the list.

- + nums = [9, 3, 8, 11, 5, 29, 2] best_num = nums[0] @@ -90,11 +90,11 @@ print(best_num)

The only thing we changed was the value of best_num on line 2 so that the value of best_num is the first element in nums, but the result is still the same!

- + Accumulating a String Result

The accumulator pattern can be used to convert a list of items to a string.

Consider the following program:

- + scores = [85, 95, 70] result = '' @@ -110,13 +110,13 @@ print("The scores are " + result)

The output of the program has some undesirable formatting problems: there is a trailing comma instead of a period, and there are no spaces between the items. The next activity lets you work to correct those problems.

- +

Let's work to improve the formatting of the sentence produced by the program above. Revise the following code so that it outputs the sentence:

The scores are 85, 95, and 70.
- + scores = [85, 95, 70] result = '' @@ -145,7 +145,7 @@ myTests().main() This solution works by iterating over all of the scores in the list except the last, and dealing with that one separately. - + scores = [85, 95, 70] result = '' for score in scores[:-1]: @@ -166,7 +166,7 @@ print("The scores are " + result)

Check your understanding

- +

What is printed by the following statements?

@@ -215,7 +215,7 @@ print(x)
- +

What is printed by the following statements?

@@ -264,11 +264,11 @@ print(min_value)
- +

Challenge For each word in words, add ‘d' to the end of the word if the word ends in e to make it past tense. Otherwise, add ‘ed' to make it past tense. Save these past tense words to a list called past_tense.

- + words = ["adopt", "bake", "beam", "confide", "grill", "plant", "time", "wave", "wish"] diff --git a/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx index 9ef9bc2ee..5ada2d706 100644 --- a/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx +++ b/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx @@ -1,10 +1,10 @@ -
+
The Accumulator Pattern with Strings

Combining the in operator with string concatenation using + and the accumulator pattern, we can write a function that removes all the vowels from a string. The idea is to start with a string and iterate over each character, checking to see if the character is a vowel. As we process the characters, we will build up a new string consisting of only the nonvowel characters. To do this, we use the accumulator pattern.

Remember that the accumulator pattern allows us to keep a running total. With strings, we are not accumulating a numeric total. Instead we are accumulating characters onto a string.

- + def removeVowels(s): vowels = "aeiouAEIOU" @@ -36,7 +36,7 @@ if eachChar != 'a' and eachChar != 'e' and eachChar != 'i' and

Take a close look also at the initialization of sWithoutVowels. We start with an empty string and then begin adding new characters to the end.

Step through the function using codelens to see the accumulator variable grow.

- + def removeVowels(s): vowels = "aeiouAEIOU" @@ -52,7 +52,7 @@ print(removeVowels("compsci"))

Check your understanding

- +

What is printed by the following statements:

@@ -94,7 +94,7 @@ print(r)

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/ComplexLogic/UsingListsasParameters.ptx b/pretext/ComplexLogic/UsingListsasParameters.ptx index c774a2aa8..4a7a2b9d1 100644 --- a/pretext/ComplexLogic/UsingListsasParameters.ptx +++ b/pretext/ComplexLogic/UsingListsasParameters.ptx @@ -1,5 +1,5 @@ -
+
Using Lists as Parameters

Functions which take lists as arguments and change them during execution are called modifiers and the changes they make are called side effects. @@ -9,7 +9,7 @@ the same list that the argument is referencing. For example, the function below takes a list as an argument and multiplies each element in the list by 2:

- + def doubleStuff(aList): """ Overwrite each element in aList with double its value. """ @@ -29,7 +29,7 @@ print(things) If a function modifies the elements of a list parameter, the caller sees the change since the change is occurring to the original.

This can be easily seen in codelens. Note that after the call to doubleStuff, the formal parameter aList refers to the same object as the actual parameter things. There is only one copy of the list object itself.

- + def doubleStuff(aList): """ Overwrite each element in aList with double its value. """ diff --git a/pretext/ComplexLogic/toctree.ptx b/pretext/ComplexLogic/toctree.ptx index 61940cb1b..0a254a223 100644 --- a/pretext/ComplexLogic/toctree.ptx +++ b/pretext/ComplexLogic/toctree.ptx @@ -4,12 +4,9 @@ 4 4 4 - 4 - -4 4 - +4 4 4 4 diff --git a/pretext/Debugging/HowtoAvoidDebugging.ptx b/pretext/Debugging/HowtoAvoidDebugging.ptx index 3b643b2a7..b88c6b05d 100644 --- a/pretext/Debugging/HowtoAvoidDebugging.ptx +++ b/pretext/Debugging/HowtoAvoidDebugging.ptx @@ -43,7 +43,7 @@

Ok, let's look at an example. Let's solve the problem posed in question 3 at the end of the Simple Python Data chapter. Ask the user for the time now (in hours 0 - 23), and ask for the number of hours to wait. Your program should output what the time will be on the clock when the alarm goes off. For example, if current_time is 8 and wait_time is 5, final_time should be 13 (1 pm).

So, where to start? The problem requires two pieces of input from the user, so let's start there and make sure we can get the data we need.

- + current_time = input("what is the current time (in hours)?") wait_time = input("How many hours do you want to wait") @@ -53,7 +53,7 @@ print(wait_time)

So far so good. Now let's take the next step. We need to figure out what the time will be after waiting wait_time number of hours. A reasonable solution is to simply add wait_time to current_time and print out the result. So lets try that.

- + current_time = input("What is the current time (in hours 0 - 23)?") wait_time = input("How many hours do you want to wait") @@ -66,7 +66,7 @@ print(final_time)

Hmm, when you run this example you see that something unexpected has happened. You would not realize this was an error unless you first knew what the program was supposed to do.

- +

Which of the following best describes what is wrong with the previous example?

@@ -99,7 +99,7 @@ print(final_time)

This error was probably pretty simple to spot, because we printed out the value of final_time and it is easy to see that the numbers were just concatenated together rather than added.

So what do we do about the problem? We will need to convert both current_time and wait_time to int. At this stage of your programming development, it can be a good idea to include the type of the variable in the variable name itself. So let's look at another iteration of the program that does that, and the conversion to integer.

- + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") @@ -114,7 +114,7 @@ print(final_time_int)

Now, that's a lot better, and in fact depending on the hours you chose, it may be exactly right. If you entered 8 for current_time and 5 for wait_time then 13 is correct. But if you entered 17 (5 pm) for current_time and 9 for wait_time then the result of 26 is not correct.

This illustrates an important aspect of testing: it is important to test your code on a range of inputs. It is especially important to test your code on boundary conditions. For this particular problem, you should test your program with current_time of 0, 23, and some values in between. You should test your wait_time for 0, and some larger values. What about negative numbers? Negative numbers don't make sense, and since we don't really have the tools to deal with telling the user when something is wrong we will not worry about that just yet.

So to account for those numbers that are bigger than 23, we need one final step: using the modulus operator.

- + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") diff --git a/pretext/Debugging/KnowyourerrorMessages.ptx b/pretext/Debugging/KnowyourerrorMessages.ptx index 9e83f8d55..445215c01 100644 --- a/pretext/Debugging/KnowyourerrorMessages.ptx +++ b/pretext/Debugging/KnowyourerrorMessages.ptx @@ -17,7 +17,7 @@ print(final_time_int)

Can you see what is wrong, just by looking at the code? Maybe, maybe not. Our brain tends to see what we think is there, so sometimes it is very hard to find the problem just by looking at the code. Especially when it is our own code and we are sure that we have done everything right!

Let's try the program again, but this time in an activecode:

- + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") @@ -35,7 +35,7 @@ print(final_time_int) Python interpreter. The interpreter in activecode is limited in many ways, but it is intended for beginners, including the wording chosen to describe errors.

- +

Which of the following explains why wait_time_int = int(wait_time_int) is an error?

@@ -296,7 +296,7 @@ print(final_time_int) TypeError

TypeErrors occur when you you try to combine two objects that are not compatible. For example you try to add together an integer and a string. Usually type errors can be isolated to lines that are using mathematical operators, and usually the line number given by the error message is an accurate indication of the line.

Here's an example of a type error created by a Polish learner. See if you can find and fix the error.

- + a = input('wpisz godzine') x = input('wpisz liczbe godzin') @@ -332,7 +332,7 @@ print ('godzina teraz', a) NameError

Name errors almost always mean that you have used a variable before it has a value. Often NameErrors are simply caused by typos in your code. They can be hard to spot if you don't have a good eye for catching spelling mistakes. Other times you may simply mis-remember the name of a variable or even a function you want to call. You have seen one example of a NameError at the beginning of this section. Here is another one. See if you can get this program to run successfully:

- + str_time = input("What time is it now?") str_wait_time = input("What is the number of nours to wait?") @@ -361,7 +361,7 @@ print(time_when_alarm_go_off)

Here is another one for you to try:

- + n = input("What time is it now (in hours)?") n = imt(n) @@ -378,7 +378,7 @@ print("The time is now", q)

And one last bit of code to fix.

- + present_time = input("Enter the present timein hours:") set_alarm = input("Set the hours for alarm:") @@ -422,7 +422,7 @@ print(alarm_time) ValueError

Value errors occur when you pass a parameter to a function and the function is expecting a certain limitations on the values, and the value passed is not compatible. We can illustrate that with this particular program in two different ways.

- + current_time_str = input("What is the current time (in hours 0-23)?") current_time_int = int(current_time_str) diff --git a/pretext/Files/AlternativeFileReadingMethods.ptx b/pretext/Files/AlternativeFileReadingMethods.ptx index 494965c5c..840c794e4 100644 --- a/pretext/Files/AlternativeFileReadingMethods.ptx +++ b/pretext/Files/AlternativeFileReadingMethods.ptx @@ -120,7 +120,7 @@

Now let's look at another method of reading our file using a while loop. This is important because many other programming languages do not support the for loop style for reading files but they do support the pattern we'll show you here.

- + infile = open("ccdata.txt", "r") line = infile.readline() diff --git a/pretext/Files/Iteratingoverlinesinafile.ptx b/pretext/Files/Iteratingoverlinesinafile.ptx index da9ccf0f7..c86a48b21 100644 --- a/pretext/Files/Iteratingoverlinesinafile.ptx +++ b/pretext/Files/Iteratingoverlinesinafile.ptx @@ -44,7 +44,7 @@ the split method, we can break each line into a list containing all the fields of interest about climate change. We can then take the values corresponding to year, global average temperature, and global emmisions to construct a simple sentence.

- + ccfile = open("ccdata.txt", "r") diff --git a/pretext/Files/ReadingCSV.ptx b/pretext/Files/ReadingCSV.ptx index 3a91fe72a..c12bea915 100644 --- a/pretext/Files/ReadingCSV.ptx +++ b/pretext/Files/ReadingCSV.ptx @@ -11,7 +11,7 @@ This section focuses on reading csv, so we should use a reader. The reason we are interested in doing this is because the reader will automatically detect and remove the commas separating values for us. Essentially, the reader will split the data up into lists for us. This makes it simpler to navigate and interact with the data in the file.

Let's see an example of this working.

- + import csv with open("ccdata.csv", "r") as file: diff --git a/pretext/Files/WithStatements.ptx b/pretext/Files/WithStatements.ptx index 0bee04a3e..a067be262 100644 --- a/pretext/Files/WithStatements.ptx +++ b/pretext/Files/WithStatements.ptx @@ -10,7 +10,7 @@

When the program exits the with block, the context manager handles the common stuff that normally happens. For example closing a file. A simple example will clear up all of this abstract discussion of contexts.

- + with open('mydata.txt') as md: print(md) diff --git a/pretext/Files/WritingCSV.ptx b/pretext/Files/WritingCSV.ptx index ee265ce73..fdd8682d4 100644 --- a/pretext/Files/WritingCSV.ptx +++ b/pretext/Files/WritingCSV.ptx @@ -4,7 +4,7 @@

We already introduced the csv module in the previous section. Let's examine some examples using a csv.writer object.

Like the reader object, the csv.writer function takes a opened file object. Once set up, the csv file can be written to with writerow. Make note that writerow does not need an explicit newline character \n to know when to end a line of text. This sets it apart for the the regular file.write() function.

- + import csv data = [["Column_1_Name","Column_2_Name","Column_3_Name"], @@ -27,7 +27,7 @@ with open("new_file.csv", "w", newline='') as file:

There is one other writer method you may find useful, which is writerows. This allows you to write multiple rows of data at the same time. When applied to the previous example, it saves us from having to set up a loop.

- + import csv diff --git a/pretext/Files/WritingTextFiles.ptx b/pretext/Files/WritingTextFiles.ptx index 4608f27c9..94cf90df1 100644 --- a/pretext/Files/WritingTextFiles.ptx +++ b/pretext/Files/WritingTextFiles.ptx @@ -9,7 +9,7 @@

To construct this file, we will approach the problem using a similar algorithm as above. After opening the file, we will iterate through the lines, break each line into its parts, choose the parts that we need, and then output them. Eventually, the output will be written to a file.

The program below solves part of the problem. Notice that it reads the data and creates a string consisting of the year of the climate change followed by the global emission. In this example, we simply print the lines as they are created.

- + infile = open("ccdata.txt", "r") aline = infile.readline() @@ -26,7 +26,7 @@ infile.close()

When we run this program, we see the lines of output on the screen. Once we are satisfied that it is creating the appropriate output, the next step is to add the necessary pieces to produce an output file and write the data lines to it. To start, we need to open a new output file by adding another call to the open function, outfile = open("emissiondata.txt",'w'), using the 'w' flag. We can choose any file name we like. If the file does not exist, it will be created. However, if the file does exist, it will be reinitialized as empty and you will lose any previous contents.

Once the file has been created, we just need to call the write method passing the string that we wish to add to the file. In this case, the string is already being printed so we will just change the print into a call to the write method. However, there is one additional part of the data line that we need to include. The newline character needs to be concatenated to the end of the line. The entire line now becomes outfile.write(dataline + '\n'). We also need to close the file when we are done.

The complete program is shown below.

- + infile = open("ccdata.txt", "r") outfile = open("emissiondata.txt", "w") diff --git a/pretext/Functions/BooleanFunctions.ptx b/pretext/Functions/BooleanFunctions.ptx index 9acd737e2..b64719bc1 100644 --- a/pretext/Functions/BooleanFunctions.ptx +++ b/pretext/Functions/BooleanFunctions.ptx @@ -1,11 +1,11 @@ -
+
Boolean Functions

We have already seen that boolean values result from the evaluation of boolean expressions. Since the result of any expression evaluation can be returned by a function (using the return statement), functions can return boolean values. This turns out to be a very convenient way to hide the details of complicated tests. For example:

- + def isDivisible(x, y): if x % y == 0: @@ -47,7 +47,7 @@ else: not isDivisible(x, y)). The following example shows the isDivisible function at work. Notice how descriptive the code is when we move the testing details into a boolean function. Try it with a few other actual parameters to see what is printed.

- + def isDivisible(x, y): return x % y == 0 @@ -60,7 +60,7 @@ else:

Here is the same program in codelens. When we evaluate the if statement in the main part of the program, the evaluation of the boolean expression causes a call to the isDivisible function. This is very easy to see in codelens.

- + def isDivisible(x, y): return x % y == 0 @@ -74,7 +74,7 @@ else:

Check your understanding

- +

What is a Boolean function?

@@ -105,7 +105,7 @@ else:
- +

Is the following statement legal in a Python function (assuming x, y and z are defined to be numbers)?

@@ -134,12 +134,12 @@ return x + y < z
- + More Unit Testing

When we write unit tests, we should also consider output equivalence classes that result in significantly different results.

The isDivisible function can return either True or False. These two different outputs give us two equivalence classes. We then choose inputs that should give each of the different results. It is important to have at least one test for each output equivalence class.

- + def isDivisible(x, y): '''is x evenly divisible by y?''' @@ -155,7 +155,7 @@ if __name__ == "__main__":

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/Functions/Composition.ptx b/pretext/Functions/Composition.ptx index 182f5dfeb..7f5ce7620 100644 --- a/pretext/Functions/Composition.ptx +++ b/pretext/Functions/Composition.ptx @@ -24,7 +24,7 @@ return result

Wrapping that up in a function, we get:

- + def distance(x1, y1, x2, y2): dx = x2 - x1 diff --git a/pretext/Functions/FlowofExecutionSummary.ptx b/pretext/Functions/FlowofExecutionSummary.ptx index 2c27227b0..7a8cbeeec 100644 --- a/pretext/Functions/FlowofExecutionSummary.ptx +++ b/pretext/Functions/FlowofExecutionSummary.ptx @@ -28,7 +28,7 @@

Check your understanding

- +

Consider the following Python code. Note that line numbers are included on the left.

@@ -91,7 +91,7 @@ print(result)
- +

Consider the following Python code. Note that line numbers are included on the left.

diff --git a/pretext/Functions/Functionscancallotherfunctions.ptx b/pretext/Functions/Functionscancallotherfunctions.ptx index 692aee804..c98720523 100644 --- a/pretext/Functions/Functionscancallotherfunctions.ptx +++ b/pretext/Functions/Functionscancallotherfunctions.ptx @@ -11,7 +11,7 @@ first function called square simply computes the square of a given number. The second function called sum_of_squares makes use of square to compute the sum of three numbers that have been squared.

- + def square(x): y = x * x diff --git a/pretext/Functions/Functionsthatreturnvalues.ptx b/pretext/Functions/Functionsthatreturnvalues.ptx index 743ea4faf..f5812b9f8 100644 --- a/pretext/Functions/Functionsthatreturnvalues.ptx +++ b/pretext/Functions/Functionsthatreturnvalues.ptx @@ -5,7 +5,7 @@ job. For example, if you want to find the absolute value of a number, you have to indicate what the number is. Python has a built-in function for computing the absolute value:

- + print(abs(5)) @@ -14,7 +14,7 @@ print(abs(-5))

In this example, the arguments to the abs function are 5 and -5.

Some functions take more than one argument. For example the range function that we saw with for loops.

- + print(list(range(4, 8))) print(list(range(1, 10))) @@ -25,7 +25,7 @@ print(abs(-5))

Another built-in function that takes more than one argument is max.

- + print(max(7, 11)) print(max(4, 1, 17, 2, 12)) @@ -55,7 +55,7 @@ print(max(3 * 11, 5 ** 3, 512 - 9, 1024 ** 0)) as a parameter and return the result of squaring that number. Here is the black-box diagram with the Python code following.

- + def square(x): y = x * x @@ -93,7 +93,7 @@ print("The result of", toSquare, "squared is", result) we will see later where it makes sense to have a return statement even when other statements follow, and the further statements are not executed.

- + def square(x): y = x * x @@ -130,7 +130,7 @@ print("The result of", toSquare, "squared is", squareResult) programmers. As you step through this example, pay very close attention to the return value in the local variables listing. Then look at what is printed when the function returns.

- + def square(x): y = x * x @@ -148,7 +148,7 @@ print("The result of", toSquare, "squared is", squareResult)

Check your understanding

- +

What is wrong with the following function definition:

@@ -194,7 +194,7 @@ def addEm(x, y, z):
- +

What will the following function return?

diff --git a/pretext/Functions/ProgramDevelopment.ptx b/pretext/Functions/ProgramDevelopment.ptx index d86150a1f..c2cbbf371 100644 --- a/pretext/Functions/ProgramDevelopment.ptx +++ b/pretext/Functions/ProgramDevelopment.ptx @@ -29,7 +29,7 @@ def distance(x1, y1, x2, y2): returns zero. But it is syntactically correct, and it will run, which means that we can test it before we make it more complicated.

We import the test module to enable us to write a unit test for the function.

- + import test def distance(x1, y1, x2, y2): @@ -83,7 +83,7 @@ def distance(x1, y1, x2, y2): should be 25).

Finally, using the fractional exponent 0.5 to find the square root, we compute and return the result.

- + import test def distance(x1, y1, x2, y2): diff --git a/pretext/Functions/TheAccumulatorPattern.ptx b/pretext/Functions/TheAccumulatorPattern.ptx index 4cf6f9576..024174902 100644 --- a/pretext/Functions/TheAccumulatorPattern.ptx +++ b/pretext/Functions/TheAccumulatorPattern.ptx @@ -22,7 +22,7 @@

Here is the program in activecode. Note that the heading of the function definition is the same as it was before. All that has changed is the details of how the squaring is done. This is a great example of black box design. We can change out the details inside of the box and still use the function exactly as we did before.

- + def square(x): runningtotal = 0 @@ -47,7 +47,7 @@ print("The result of", toSquare, "squared is", squareResult) the for statement? Not sure? Try it and find out.

Here is the same program in codelens. Step through the function and watch the running total accumulate the result.

- + def square(x): runningtotal = 0 @@ -75,7 +75,7 @@ repeat:

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -85,7 +85,7 @@ repeat:

Check your understanding

- +

Consider the following code:

@@ -162,7 +162,7 @@ def square(x):
A Variation on the Accumulator Pattern - + def square(x): '''raise x to the second power''' diff --git a/pretext/Functions/UnitTesting.ptx b/pretext/Functions/UnitTesting.ptx index 5d995f943..7c17cda8f 100644 --- a/pretext/Functions/UnitTesting.ptx +++ b/pretext/Functions/UnitTesting.ptx @@ -39,7 +39,7 @@

Take a look at the way assert is used in the following code.

- + assert type(9//5) == int assert type(9.0//5) == int @@ -55,7 +55,7 @@ assert type(9.0//5) == int

Check your understanding

- +

When assert x==y is executed and x and y have the same values, what will happen?

@@ -118,7 +118,7 @@ assert type(9.0//5) == int

In the code below, lst is bound to a list object. In python, not all the elements of a list have to be of the same type. We can check that they all have the same type and get an error if they are not. Notice that with lst2, one of the assertions fails.

- + lst = ['a', 'b', 'c'] first_type = type(lst[0]) @@ -137,7 +137,7 @@ for item in lst2:

Testing whether a function returns the correct value is the easiest test case to define. You simply check whether the result of invoking the function on a particular input produces the particular output that you expect. Take a look at the following code.

- + def square(x): #raise x to the second power @@ -150,7 +150,7 @@ assert square(3) == 9 principle, a function might work properly on all the inputs that are tested in the test cases, but still not work properly on some other inputs. That's where the art of defining test cases comes in: you try to find specific inputs that are representative of all the important kinds of inputs that might ever be passed to the function.

- +

For the hangman game, this ‘blanked' function takes a word and some letters that have been guessed, and returns a version of the word with _ for all the letters that haven't been guessed. Which of the following is the correct way to write diff --git a/pretext/Functions/Variablesandparametersarelocal.ptx b/pretext/Functions/Variablesandparametersarelocal.ptx index 3451b4f86..f0c8e2a0c 100644 --- a/pretext/Functions/Variablesandparametersarelocal.ptx +++ b/pretext/Functions/Variablesandparametersarelocal.ptx @@ -5,7 +5,7 @@ variable on the left hand side of the assignment operator. It is called local because this variable only exists inside the function and you cannot use it outside. For example, consider again the square function:

- + def square(x): y = x * x @@ -39,7 +39,7 @@

On the other hand, it is legal for a function to access a global variable. However, this is considered bad form by nearly all programmers and should be avoided. Look at the following, nonsensical variation of the square function.

- + def badsquare(x): y = x ** power @@ -62,7 +62,7 @@ print(result)

There is another variation on this theme of local versus global variables. Assignment statements in the local function cannot change variables defined outside the function, without further (discouraged) special syntax. Consider the following codelens example:

- + def powerof(x, p): power = p # Another dumb mistake @@ -96,7 +96,7 @@ print(result) formal parameter will cause a change to the value of the variable that was used as the actual parameter, especially when the two share the same name. But this example demonstrates that that is clearly not how Python operates.

- + def square(x): y = x * x @@ -111,7 +111,7 @@ print(result)

Check your understanding

- +

What is a variable's scope?

@@ -142,7 +142,7 @@ print(result)
- +

What is a local variable?

@@ -173,7 +173,7 @@ print(result)
- +

Can you use the same name for a local variable as a global variable?

diff --git a/pretext/Functions/functions.ptx b/pretext/Functions/functions.ptx index 2309236e7..bd3b5a301 100644 --- a/pretext/Functions/functions.ptx +++ b/pretext/Functions/functions.ptx @@ -49,7 +49,7 @@ def name( parameters ): It would make sense if we did not have to duplicate all the steps each time we want to find the size of the range. "printRange" can be thought of as an abstraction of a number of smaller steps. We will need to provide one piece of information for the function to do its work: the list we need the range of.

Here is a program containing a function to capture this idea. Give it a try.

- + def printRange(lst): """Prints the size of the range of lst.""" @@ -88,7 +88,7 @@ def name( parameters ):

Once we've defined a function, we can call it as often as we like and its statements will be executed each time we call it. In this case, we could use it to get the size of the range of multiple lists. Make sure you can identify all three invocations of the printRange function.

- + def printRange(lst): """Prints the size of the range of lst.""" @@ -113,7 +113,7 @@ printRange([5, 10, 1000, 2])

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -123,7 +123,7 @@ printRange([5, 10, 1000, 2])

Check your understanding

- +

What is a function in Python?

@@ -162,7 +162,7 @@ printRange([5, 10, 1000, 2])
- +

What is one main purpose of a function?

@@ -201,7 +201,7 @@ printRange([5, 10, 1000, 2])
- +

Which of the following is a valid function header (first line of a function definition)?

@@ -240,7 +240,7 @@ printRange([5, 10, 1000, 2])
- +

What is the name of the following function?

@@ -287,7 +287,7 @@ def printSquare(size):
- +

What are the parameters of the following function?

@@ -334,7 +334,7 @@ def printSquare(size):
- +

Considering the function below, which of the following statements correctly invokes, or calls, this function (i.e., causes it to run)? Assume we already have a variable named my_size.

@@ -389,7 +389,7 @@ def printSquare(size):
- +

True or false: A function can be called several times by placing a function call in the body of a loop.

diff --git a/pretext/Functions/mainfunction.ptx b/pretext/Functions/mainfunction.ptx index 41777c53f..5b11ec7e2 100644 --- a/pretext/Functions/mainfunction.ptx +++ b/pretext/Functions/mainfunction.ptx @@ -29,7 +29,7 @@ print("The result of", toSquare, "squared is", squareResult) piece main.

The following activecode shows this idea. In line 11 we have defined a new function called main that doesn't need any parameters. The five lines of main processing are now placed inside this function. Finally, in order to execute that main processing code, we need to invoke the main function (line 20). When you push run, you will see that the program works the same as it did before.

- + def square(x): y = x * x @@ -56,7 +56,7 @@ main() # Invoke the main function

Before the Python interpreter executes your program, it defines a few special variables. One of those variables is called __name__ and it is automatically set to the string value "__main__" when the program is being executed by itself in a standalone fashion. On the other hand, if the program is being imported by another program, then the __name__ variable is set to the name of that module. This means that we can know whether the program is being run by itself or whether it is being used by another program and based on that observation, we may or may not choose to execute some of the code that we have written.

For example, assume that we have written a collection of functions to do some simple math. We can include a main function to invoke these math functions. It is much more likely, however, that these functions will be imported by another program for some other purpose. In that case, we would not want to execute our main function.

The activecode below defines two simple functions and a main.

- + def squareit(n): return n * n diff --git a/pretext/GeneralIntro/ATypicalFirstProgram.ptx b/pretext/GeneralIntro/ATypicalFirstProgram.ptx index 4bb8512e0..5c72c40a5 100644 --- a/pretext/GeneralIntro/ATypicalFirstProgram.ptx +++ b/pretext/GeneralIntro/ATypicalFirstProgram.ptx @@ -13,7 +13,7 @@ print("Hello, World!") print anything on paper. It displays a value on the screen. In this case, the result is the phrase:

Hello, World!

Here is the example in activecode. Give it a try!

- + print("Hello, World!") @@ -26,7 +26,7 @@ print("Hello, World!")

Check your understanding

- +

The print function:

diff --git a/pretext/GeneralIntro/Algorithms.ptx b/pretext/GeneralIntro/Algorithms.ptx index f11cdf1ad..cc3de8da5 100644 --- a/pretext/GeneralIntro/Algorithms.ptx +++ b/pretext/GeneralIntro/Algorithms.ptx @@ -10,7 +10,7 @@

Check your understanding

- +

What is the most important skill for a computer scientist?

@@ -49,7 +49,7 @@
- +

An algorithm is:

diff --git a/pretext/GeneralIntro/Comments.ptx b/pretext/GeneralIntro/Comments.ptx index 8c3159fd1..c9fe4a8ef 100644 --- a/pretext/GeneralIntro/Comments.ptx +++ b/pretext/GeneralIntro/Comments.ptx @@ -10,7 +10,7 @@ reader - it is completely ignored by the interpreter. In Python, the # token starts a comment. The rest of the line is ignored. Here is a new version of Hello, World!.

- + #--------------------------------------------------- # This demo program shows off how elegant Python is! @@ -28,7 +28,7 @@ print("Hello, World!") # Isn't this easy!

Check your understanding

- +

What are comments for?

diff --git a/pretext/GeneralIntro/ExperimentalDebugging.ptx b/pretext/GeneralIntro/ExperimentalDebugging.ptx index 771a5519c..ab52525e9 100644 --- a/pretext/GeneralIntro/ExperimentalDebugging.ptx +++ b/pretext/GeneralIntro/ExperimentalDebugging.ptx @@ -28,7 +28,7 @@

Check your understanding

- +

The difference between programming and debugging is:

diff --git a/pretext/GeneralIntro/FormalandNaturalLanguages.ptx b/pretext/GeneralIntro/FormalandNaturalLanguages.ptx index e6cb1eb25..944a98f84 100644 --- a/pretext/GeneralIntro/FormalandNaturalLanguages.ptx +++ b/pretext/GeneralIntro/FormalandNaturalLanguages.ptx @@ -100,7 +100,7 @@

Check your understanding

- +

The differences between natural and formal languages include:

@@ -139,7 +139,7 @@
- +

True or False: Reading a program is like reading other kinds of text.

diff --git a/pretext/GeneralIntro/MoreAboutPrograms.ptx b/pretext/GeneralIntro/MoreAboutPrograms.ptx index 4ba5be1e9..3c06b0556 100644 --- a/pretext/GeneralIntro/MoreAboutPrograms.ptx +++ b/pretext/GeneralIntro/MoreAboutPrograms.ptx @@ -43,7 +43,7 @@

Check your understanding

- +

A program is:

diff --git a/pretext/GeneralIntro/RuntimeErrors.ptx b/pretext/GeneralIntro/RuntimeErrors.ptx index 71b4d6b61..8ef4ac3e1 100644 --- a/pretext/GeneralIntro/RuntimeErrors.ptx +++ b/pretext/GeneralIntro/RuntimeErrors.ptx @@ -10,7 +10,7 @@

Check your understanding

- +

Which of the following is a run-time error?

@@ -41,7 +41,7 @@
- +

Who or what typically finds runtime errors?

diff --git a/pretext/GeneralIntro/SemanticErrors.ptx b/pretext/GeneralIntro/SemanticErrors.ptx index d303e2468..5f456c276 100644 --- a/pretext/GeneralIntro/SemanticErrors.ptx +++ b/pretext/GeneralIntro/SemanticErrors.ptx @@ -12,7 +12,7 @@

Check your understanding

- +

Which of the following is a semantic error?

@@ -43,7 +43,7 @@
- +

Who or what typically finds semantic errors?

diff --git a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx index 0c8dd18a6..82c475526 100644 --- a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx +++ b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx @@ -7,7 +7,7 @@

First, you can write, modify, and execute programs using a unique activecode interpreter that allows you to execute Python code right in the text itself (right from the web browser). Although this is certainly not the way real programs are written, it provides an excellent environment for learning a programming language like Python since you can experiment with the language as you are reading.

- + print("My first program adds two numbers, 2 and 3:") print(2 + 3) @@ -53,7 +53,7 @@ print(2 + 3) In codelens you can see and control the step by step progress. Note that the red arrow always points to the next line of code that is going to be executed. The light green arrow points to the line that was just executed.

- + print("My first program adds two numbers, 2 and 3:") print(2 + 3) @@ -65,7 +65,7 @@ print(2 + 3)

Check your understanding

- +

The activecode interpreter allows you to (select all that apply):

@@ -104,7 +104,7 @@ print(2 + 3)
- +

Codelens allows you to (select all that apply):

diff --git a/pretext/GeneralIntro/Syntaxerrors.ptx b/pretext/GeneralIntro/Syntaxerrors.ptx index ef3ac5a61..181b4f5ec 100644 --- a/pretext/GeneralIntro/Syntaxerrors.ptx +++ b/pretext/GeneralIntro/Syntaxerrors.ptx @@ -16,7 +16,7 @@

Check your understanding

- +

Which of the following is a syntax error?

@@ -47,7 +47,7 @@
- +

Who or what typically finds syntax errors?

diff --git a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx index ff6c7ed7a..33491dac4 100644 --- a/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx +++ b/pretext/GeneralIntro/ThePythonProgrammingLanguage.ptx @@ -74,7 +74,7 @@ My first program adds two numbers, 2 and 3:

Check your understanding

- +

Source code is another name for:

@@ -113,7 +113,7 @@ My first program adds two numbers, 2 and 3:
- +

What is the difference between a high-level programming language and a low-level programming language?

@@ -154,7 +154,7 @@ My first program adds two numbers, 2 and 3: - +

Pick the best replacements for 1 and 2 in the following sentence: When comparing compilers and interpreters, a compiler is like 1 while an interpreter is like 2.

diff --git a/pretext/GeneralIntro/WhatisDebugging.ptx b/pretext/GeneralIntro/WhatisDebugging.ptx index 5d065d654..babc98c0f 100644 --- a/pretext/GeneralIntro/WhatisDebugging.ptx +++ b/pretext/GeneralIntro/WhatisDebugging.ptx @@ -12,7 +12,7 @@

Check your understanding

- +

Debugging is:

diff --git a/pretext/IntroRecursion/CalculatingtheSumofaListofNumbers.ptx b/pretext/IntroRecursion/CalculatingtheSumofaListofNumbers.ptx index a5ceb8a32..a3e867a89 100644 --- a/pretext/IntroRecursion/CalculatingtheSumofaListofNumbers.ptx +++ b/pretext/IntroRecursion/CalculatingtheSumofaListofNumbers.ptx @@ -8,7 +8,7 @@ is shown below. The function uses an accumulator variable (theSum) to compute a running total of all the numbers in the list by starting with 0 and adding each number in the list.

- + def listsum(numList): theSum = 0 @@ -51,7 +51,7 @@ total = \ 25

In this equation first(numList) returns the first element of the list and rest(numList) returns a list of everything but the first element. This is easily expressed in Python.

- + def listsum(numList): if len(numList) == 1: diff --git a/pretext/IntroRecursion/ConvertinganIntegertoaStringinAnyBase.ptx b/pretext/IntroRecursion/ConvertinganIntegertoaStringinAnyBase.ptx index b2b8e09c5..001d14112 100644 --- a/pretext/IntroRecursion/ConvertinganIntegertoaStringinAnyBase.ptx +++ b/pretext/IntroRecursion/ConvertinganIntegertoaStringinAnyBase.ptx @@ -58,7 +58,7 @@

The activecode below shows the Python code that implements the algorithm outlined above for any base between 2 and 16.

- + def toStr(n,base): convertString = "0123456789ABCDEF" @@ -93,7 +93,7 @@ print(toStr(1453,16)) Self Check

Write a function that takes a string as a parameter and returns a new string that is the reverse of the old string.

- + from test import testEqual def reverse(s): @@ -134,7 +134,7 @@ testEqual(reverse(""),"")

- + from test import testEqual def removeWhite(s): diff --git a/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx b/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx index 9d4bddde1..0c086c4d3 100644 --- a/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx +++ b/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx @@ -46,7 +46,7 @@ problem by using the three laws of recursion.

Self Check - +

How many recursive calls are made when computing the sum of the list [2,4,6,8,10]?

@@ -85,7 +85,7 @@
- +

Suppose you are going to write a recusive function to calculate the factorial of a number. fact(n) returns n * n-1 * n-2 * … * 1, and the factorial of zero is definded to be 1. What would be the most appropriate base case?

diff --git a/pretext/Iteration/BreakAndContinue.ptx b/pretext/Iteration/BreakAndContinue.ptx index 8f13f7198..6c7af97be 100644 --- a/pretext/Iteration/BreakAndContinue.ptx +++ b/pretext/Iteration/BreakAndContinue.ptx @@ -1,5 +1,5 @@ -
+
<c>break</c> and <c>continue</c>

In loops, we sometimes want to traverse until we reach a certain value. @@ -9,7 +9,7 @@

When a break statement is reached, the loop immediately ends and proceeds with the code after the loop. break is only a valid statement inside of loops, such as the following:

- + i = 0 while i < 10: @@ -24,7 +24,7 @@ while i < 10: When a continue statement is reached, the current iteration is stopped (similar to break), however, the loop will continue running for all iterations after the current one.

- + i = 0 while i < 10: diff --git a/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx index 674266a21..cdc423eca 100644 --- a/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx +++ b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx @@ -1,5 +1,5 @@ -
+
Flow of Execution of the while Loop

As before with if, loops allow us as programmers to manipulate the control flow of a Python program. We can now possibly skip a portion of code, or choose to repeat it an indefinite number of times.

@@ -8,7 +8,7 @@

A codelens demonstration is a good way to help you visualize exactly how the flow of control works with the while loop. Try stepping forward and backward through the program by pressing the buttons. You can see the value of count change as the loop iterates through the values from 10 to 0.

- + count = 10 while count > 0: diff --git a/pretext/Iteration/Glossary.ptx b/pretext/Iteration/Glossary.ptx index 1a1e4a6ff..8ea715a88 100644 --- a/pretext/Iteration/Glossary.ptx +++ b/pretext/Iteration/Glossary.ptx @@ -79,6 +79,11 @@ tab

A special character that causes the cursor to move to the next tab stop on the current line.

+ + + traverse +

To iterate through the elements of a collection, performing a similar + operation on each.

diff --git a/pretext/Iteration/Listsandforloops.ptx b/pretext/Iteration/Listsandforloops.ptx index 872c053ab..b3d7b04b2 100644 --- a/pretext/Iteration/Listsandforloops.ptx +++ b/pretext/Iteration/Listsandforloops.ptx @@ -1,8 +1,8 @@ -
+
Traversing lists with the <c>for</c> loop -

It is also possible to perform list traversal using iteration by item as well as iteration by index.

- +

It is possible to perform list traversal using iteration by item as well as iteration by index.

+ fruits = ["apple", "orange", "banana", "cherry"] @@ -13,7 +13,7 @@ for afruit in fruits: # by item

It almost reads like natural language: For (every) fruit in (the list of) fruits, print (the name of the) fruit.

We can also use the indices to access the items in an iterative fashion.

- + fruits = ["apple", "orange", "banana", "cherry"] @@ -25,7 +25,7 @@ for position in range(len(fruits)): # by index list, printing the position-eth element. Note that we used len as the upper bound on the range so that we can iterate correctly no matter how many items are in the list.

Any sequence expression can be used in a for loop. For example, the range function returns a sequence of integers.

- + for number in range(20): if number % 3 == 0: @@ -36,7 +36,7 @@ for number in range(20):

Since lists are mutable, it is often desirable to traverse a list, modifying each of its elements as you go. The following code squares all the numbers from 1 to 5 using iteration by position.

- + numbers = [1, 2, 3, 4, 5] print(numbers) @@ -53,7 +53,7 @@ print(numbers)

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/Iteration/SentinelValuesAndValidation.ptx b/pretext/Iteration/SentinelValuesAndValidation.ptx index cbc33af57..0e5321576 100644 --- a/pretext/Iteration/SentinelValuesAndValidation.ptx +++ b/pretext/Iteration/SentinelValuesAndValidation.ptx @@ -1,7 +1,7 @@ -
+
Other uses of <c>while</c> - + Sentinel Values

The indefinite loops provided by the while statement are common in the real world.

@@ -53,7 +53,7 @@ We don't have a little plastic bar data type in Python, so we'll do the next best thing: we will use a price of zero to mean this is my last item. In this program, zero is a sentinel value, a value used to signal the end of the loop. Here's the code:

- + total = 0 count = 0 @@ -91,7 +91,7 @@

Check your understanding

- +

True or False: A while loop will continue to iterate forever unless it meets a condition to stop.

@@ -118,7 +118,7 @@

- + Validating Input

You can also use a while loop when you want to validate input; when you want to make sure the user has entered valid input for a prompt. Let's say you want a function @@ -128,7 +128,7 @@ Note that it uses the upper() method which is described in to convert a string to upper case. When you run the following code, try typing something other than Y or N to see how the code reacts:

- + valid_input = False response = input('Do you like lima beans? Y)es or N)o: ') diff --git a/pretext/Iteration/The3n1Sequence.ptx b/pretext/Iteration/The3n1Sequence.ptx index 40e4c4150..53cb7d31c 100644 --- a/pretext/Iteration/The3n1Sequence.ptx +++ b/pretext/Iteration/The3n1Sequence.ptx @@ -1,5 +1,5 @@ -
+
The 3n + 1 Sequence

As another example of iteration with while, let's look at a sequence that has fascinated mathematicians for many years. The rule for creating the sequence is to start from @@ -8,7 +8,7 @@ whenever n is even, or else by multiplying it by three and adding 1 when it is odd. The sequence terminates when n reaches 1.

This Python code captures that algorithm. Try running this program several times supplying different values for n.

- + n = 3 @@ -63,10 +63,10 @@ -

+

Check your understanding

- +

Consider the code that prints the 3n+1 sequence in ActiveCode box 6. Will the while loop in this code always terminate for any positive integer value of n?

diff --git a/pretext/Iteration/TheforLoop.ptx b/pretext/Iteration/TheforLoop.ptx index 3b4d6bc78..8efd54db4 100644 --- a/pretext/Iteration/TheforLoop.ptx +++ b/pretext/Iteration/TheforLoop.ptx @@ -1,5 +1,5 @@ -
+
The <c>for</c> loop

The while statement is a general-purpose tool for iteration, and is necessary for any instance of iteration where we don't know how many repetitions will be needed. However, if we do know how many are needed, there is a more efficient approach: the for statement.

@@ -7,7 +7,7 @@ However, if we do know how many are needed, there is a more efficient approach: we'd like to send them each an email inviting them to our party. We don't quite know how to send email yet, so for the moment we'll just print a message for each friend.

- + for name in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: print(f"Hi {name}! Please come to my party on Saturday!") @@ -61,7 +61,7 @@ terminates.

Check your understanding - +

True or False: You can rewrite any for-loop as a while-loop.

diff --git a/pretext/Iteration/TherangeFunction.ptx b/pretext/Iteration/TherangeFunction.ptx index a3bd46c3b..a3940ade1 100644 --- a/pretext/Iteration/TherangeFunction.ptx +++ b/pretext/Iteration/TherangeFunction.ptx @@ -1,5 +1,5 @@ -
+
The range Function

In our first example of a while loop, we counted down from 10 to 0. If we were to consider doing this with a for loop, we would need to construct our own series of numbers @@ -57,7 +57,7 @@ for x in range(10):

Here are two examples for you to run. Try them and then add another line below to create a sequence starting at 10 and going up to 20 (including 20).

- + print(list(range(4))) print(list(range(1, 5))) @@ -65,7 +65,7 @@ print(list(range(1, 5)))

Codelens will help us to further understand the way range works. In this case, the variable i will take on values produced by the range function.

- + for i in range(10): print(i) @@ -78,7 +78,7 @@ print(list(range(1, 5))) range(0,19,2). The most general form of the range is range(start, beyondLast, step). You can also create a sequence of numbers that starts big and gets smaller by using a negative value for the step parameter.

- + print(list(range(0, 19, 2))) print(list(range(0, 20, 2))) @@ -86,7 +86,7 @@ print(list(range(10, 0, -1)))

Try it in codelens. Do you see why the first two statements produce the same result?

- + for i in range(0, 20, 2): print(i) @@ -95,7 +95,7 @@ for i in range(0, 20, 2):

Check your understanding

- +

In the command range(3, 10, 2), what does the second argument (10) specify?

@@ -134,7 +134,7 @@ for i in range(0, 20, 2):
- +

What command correctly generates the sequence 2, 5, 8?

@@ -173,7 +173,7 @@ for i in range(0, 20, 2):
- +

What happens if you give range only one argument? For example: range(4)

@@ -212,7 +212,7 @@ for i in range(0, 20, 2):
- +

Which range function call will produce the sequence 20, 15, 10, 5?

@@ -251,7 +251,7 @@ for i in range(0, 20, 2):
- +

What could the second parameter (12) in range(2, 12, 4) be replaced with and generate exactly the same sequence?

diff --git a/pretext/Iteration/ThewhileStatement.ptx b/pretext/Iteration/ThewhileStatement.ptx index 07e20b14d..4a1eca840 100644 --- a/pretext/Iteration/ThewhileStatement.ptx +++ b/pretext/Iteration/ThewhileStatement.ptx @@ -1,5 +1,5 @@ -
+
The <c>while</c> Statement

Let's look at our first Python statement that can be used to build an iteration. It is called the while statement. When used with other code it can be used to @@ -7,7 +7,7 @@ a boolean expression to control the flow of execution. The body of while (code indented one space in) will be repeated as long as the controlling boolean expression evaluates to True.

Here is a simple example that counts down from 10 to 0.

- + count = 10 while count > 0: @@ -71,7 +71,7 @@

Here is the summation program that uses a while statement.

- + """ Return the sum of 1+2+3 ... n """ aBound = int(input("Please give a number n: ")) @@ -90,7 +90,7 @@

The same program in codelens will allow you to observe the flow of execution.

- + """ Return the sum of 1+2+3 ... n """ aBound = int(input("Please give a number n: ")) @@ -110,7 +110,7 @@

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -120,7 +120,7 @@

Check your understanding

- +

True or False: You can rewrite any for-loop as a while-loop.

@@ -143,7 +143,7 @@
- +

The following code contains an infinite loop. Which is the best explanation for why the loop does not terminate?

@@ -192,7 +192,7 @@ print(answer)
- +

What is printed by this code?

diff --git a/pretext/Iteration/TraversalandtheforLoopByIndex.ptx b/pretext/Iteration/TraversalandtheforLoopByIndex.ptx index 9850cc364..6dec6e390 100644 --- a/pretext/Iteration/TraversalandtheforLoopByIndex.ptx +++ b/pretext/Iteration/TraversalandtheforLoopByIndex.ptx @@ -1,11 +1,11 @@ -
+
Traversing strings with the <c>for</c> Loop: By Index

It is also possible to use the range function to systematically generate the indices of the characters. The for loop can then be used to iterate over these positions. These positions can be used together with the indexing operator to access the individual characters in the string.

Consider the following codelens example.

- + fruit = "apple" for idx in range(5): @@ -17,7 +17,7 @@ for idx in range(5): of the characters.

In order to make the iteration more general, we can use the len function to provide the bound for range. This is a very common pattern for traversing any sequence by position. Make sure you understand why the range function behaves correctly when using len of the string as its parameter value.

- + fruit = "apple" for idx in range(len(fruit)): @@ -27,7 +27,7 @@ for idx in range(len(fruit)):

You may also note that iteration by position allows the programmer to control the direction of the traversal by changing the sequence of index values. Recall that we can create ranges that count down as well as up so the following code will print the characters from right to left.

- + fruit = "apple" for idx in range(len(fruit)-1, -1, -1): @@ -38,7 +38,7 @@ for idx in range(len(fruit)):

Check your understanding

- +

How many times is the letter o printed by the following statements?

diff --git a/pretext/Iteration/TraversalandtheforLoopByItem.ptx b/pretext/Iteration/TraversalandtheforLoopByItem.ptx index b92453001..b46bd2125 100644 --- a/pretext/Iteration/TraversalandtheforLoopByItem.ptx +++ b/pretext/Iteration/TraversalandtheforLoopByItem.ptx @@ -1,5 +1,5 @@ -
+
Traversing strings with the <c>for</c> Loop: By Item

A lot of computations involve processing a collection one item at a time. For strings this means that we would like to process one character at a time. @@ -7,7 +7,7 @@ to it, and continue until the end. This pattern of processing is called a traversal.

We have previously seen that the for statement can iterate over the items of a sequence (a list of names in the case below).

- + for aname in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: invitation = "Hi " + aname + ". Please come to my party on Saturday!" @@ -15,14 +15,14 @@ for aname in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]:

Recall that the loop variable takes on each value in the sequence of names. The body is performed once for each name. The same was true for the sequence of integers created by the range function.

- + for avalue in range(10): print(avalue)

Since a string is simply a sequence of characters, the for loop iterates over each character automatically.

- + for achar in "Go Spot Go": print(achar) @@ -34,7 +34,7 @@ for achar in "Go Spot Go":

Check your understanding

- +

How many times is the word HELLO printed by the following statements?

@@ -80,7 +80,7 @@ for ch in s:
- +

How many times is the word HELLO printed by the following statements?

diff --git a/pretext/Iteration/TraversalandthewhileLoop.ptx b/pretext/Iteration/TraversalandthewhileLoop.ptx index 166c22bba..536875f57 100644 --- a/pretext/Iteration/TraversalandthewhileLoop.ptx +++ b/pretext/Iteration/TraversalandthewhileLoop.ptx @@ -1,11 +1,11 @@ -
+
Traversal and the <c>while</c> Loop

The while loop can also control the generation of index values used to navigate strings or lists. The programmer is responsible for setting up the initial condition, making sure that the condition is correct, and making sure that something changes inside the body to guarantee that the condition will eventually fail.

- + fruit = "apple" @@ -20,7 +20,7 @@ while position < len(fruit): executed. The last character accessed is the one with the index len(fruit)-1, which is the last character in the string.

Here is the same example in codelens so that you can trace the values of the variables.

- + fruit = "apple" @@ -33,7 +33,7 @@ while position < len(fruit):

Check your understanding

- +

How many times is the letter o printed by the following statements?

@@ -75,7 +75,7 @@ while idx < len(s):

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/Iteration/intro-Iteration.ptx b/pretext/Iteration/intro-Iteration.ptx index f34976720..d443a1be6 100644 --- a/pretext/Iteration/intro-Iteration.ptx +++ b/pretext/Iteration/intro-Iteration.ptx @@ -1,7 +1,7 @@ -
+
Iteration Introduction -

Computers are often used to automate repetitive tasks. Repeating identical or +

Computers are often used to automate repetitive tasks. Repeating identical or similar tasks without making errors is something that computers do well and people do poorly.

Repeated execution of a sequence of statements is called iteration. Because diff --git a/pretext/Lists/AccessingElements.ptx b/pretext/Lists/AccessingElements.ptx index d9cae3bd3..9d950f42e 100644 --- a/pretext/Lists/AccessingElements.ptx +++ b/pretext/Lists/AccessingElements.ptx @@ -7,7 +7,7 @@ the index. Remember that the indices start at 0. Any integer expression can be used as an index and as with strings, negative index values will locate items from the right instead of from the left.

- + numbers = [17, 123, 87, 34, 66, 8398, 44] print(numbers[2]) @@ -19,7 +19,7 @@ print(numbers[len(numbers) - 1])

Check your understanding

- +

What is printed by the following statements?

@@ -56,7 +56,7 @@ print(alist[5])
- +

What is printed by the following statements?

@@ -93,7 +93,7 @@ print(alist[2].upper())
- +

What is printed by the following statements?

diff --git a/pretext/Lists/AppendversusConcatenate.ptx b/pretext/Lists/AppendversusConcatenate.ptx index 85d82a24c..e2c457658 100644 --- a/pretext/Lists/AppendversusConcatenate.ptx +++ b/pretext/Lists/AppendversusConcatenate.ptx @@ -3,7 +3,7 @@ Append versus Concatenate

The append method adds a new item to the end of a list. It is also possible to add a new item to the end of a list by using the concatenation operator. However, you need to be careful.

Consider the following example. The original list has 3 integers. We want to add the word cat to the end of the list.

- + origlist = [45, 32, 88] @@ -13,7 +13,7 @@ origlist.append("cat")

Here we have used append which simply modifies the list. In order to use concatenation, we need to write an assignment statement that uses the accumulator pattern:

origlist = origlist + ["cat"]

Note that the word cat needs to be placed in a list since the concatenation operator needs two lists to do its work.

- + origlist = [45, 32, 88] @@ -24,7 +24,7 @@ origlist = origlist + ["cat"] On the other hand, with concatenation, an entirely new list is created. This can be seen in the following codelens example where newlist refers to a list which is a copy of the original list, origlist, with the new item cat added to the end. origlist still contains the three values it did before the concatenation. This is why the assignment operation is necessary as part of the accumulator pattern.

- + origlist = [45, 32, 88] @@ -34,7 +34,7 @@ origlist = origlist + ["cat"]

Check you understanding

- +

What is printed by the following statements?

diff --git a/pretext/Lists/CloningLists.ptx b/pretext/Lists/CloningLists.ptx index 19fb72a1c..553e88a91 100644 --- a/pretext/Lists/CloningLists.ptx +++ b/pretext/Lists/CloningLists.ptx @@ -7,7 +7,7 @@

The easiest way to clone a list is to use the slice operator.

Taking any slice of a creates a new list. In this case the slice happens to consist of the whole list.

- + a = [81, 82, 83] diff --git a/pretext/Lists/ConcatenationandRepetition.ptx b/pretext/Lists/ConcatenationandRepetition.ptx index bf5a5effa..3686f29ab 100644 --- a/pretext/Lists/ConcatenationandRepetition.ptx +++ b/pretext/Lists/ConcatenationandRepetition.ptx @@ -3,7 +3,7 @@ Concatenation and Repetition

Again, as with strings, the + operator concatenates lists. Similarly, the * operator repeats the items in a list a given number of times.

- + fruit = ["apple", "orange", "banana", "cherry"] print([1, 2] + [3, 4]) @@ -15,7 +15,7 @@ print([1, 2, ["hello", "goodbye"]] * 2)

It is important to see that these operators create new lists from the elements of the operand lists. If you concatenate a list with 2 items and a list with 4 items, you will get a new list with 6 items (not a list with two sublists). Similarly, repetition of a list of 2 items 4 times will give a list with 8 items.

One way for us to make this more clear is to run a part of this example in codelens. As you step through the code, you will see the variables being created and the lists that they refer to. Pay particular attention to the fact that when newlist is created by the statement newlist = fruit + numlist, it refers to a completely new list formed by making copies of the items from fruit and numlist. You can see this very clearly in the codelens object diagram. The objects are different.

- + fruit = ["apple", "orange", "banana", "cherry"] numlist = [6, 7] @@ -37,7 +37,7 @@ zeros = [0] * 4

Check your understanding

- +

What is printed by the following statements?

@@ -83,7 +83,7 @@ print(alist + blist)
- +

What is printed by the following statements?

diff --git a/pretext/Lists/ListDeletion.ptx b/pretext/Lists/ListDeletion.ptx index 98c5b4aad..386f02678 100644 --- a/pretext/Lists/ListDeletion.ptx +++ b/pretext/Lists/ListDeletion.ptx @@ -4,7 +4,7 @@

Using slices to delete list elements can be awkward and therefore error-prone. Python provides an alternative that is more readable. The del statement removes an element from a list by using its position.

- + a = ['one', 'two', 'three'] del a[1] @@ -22,7 +22,7 @@ print(alist) index, but do not cause runtime errors if the index limits go too far.

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/Lists/ListLength.ptx b/pretext/Lists/ListLength.ptx index c7e1ca7fb..a16bd17a6 100644 --- a/pretext/Lists/ListLength.ptx +++ b/pretext/Lists/ListLength.ptx @@ -5,7 +5,7 @@ of items in the list). However, since lists can have items which are themselves lists, it important to note that len only returns the top-most length. In other words, sublists are considered to be a single item when counting the length of the list.

- + alist = ["hello", 2.0, 5, [10, 20]] print(len(alist)) @@ -15,7 +15,7 @@ print(len(['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]))

Check your understanding

- +

What is printed by the following statements?

@@ -44,7 +44,7 @@ print(len(alist))
- +

What is printed by the following statements?

diff --git a/pretext/Lists/ListMethods.ptx b/pretext/Lists/ListMethods.ptx index 263c05652..7fb739c5e 100644 --- a/pretext/Lists/ListMethods.ptx +++ b/pretext/Lists/ListMethods.ptx @@ -5,7 +5,7 @@ append is a list method which adds the argument passed to it to the end of the list. Continuing with this example, we show several other list methods. Many of them are easy to understand.

- + mylist = [] mylist.append(5) @@ -192,7 +192,7 @@ print(mylist) can be found in the Python Documentation.

It is important to remember that methods like append, sort, and reverse all return None. This means that re-assigning mylist to the result of sorting mylist will result in losing the entire list. Calls like these will likely never appear as part of an assignment statement (see line 8 below).

- + mylist = [] mylist.append(5) @@ -208,7 +208,7 @@ print(mylist)

Check your understanding

- +

What is printed by the following statements?

@@ -247,7 +247,7 @@ print(alist)
- +

What is printed by the following statements?

@@ -286,7 +286,7 @@ print(alist)
- +

What is printed by the following statements?

@@ -325,7 +325,7 @@ print(alist)
- +

What is printed by the following statements?

@@ -373,7 +373,7 @@ print(alist)

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/Lists/ListSlices.ptx b/pretext/Lists/ListSlices.ptx index 4bdf72da5..6909e2054 100644 --- a/pretext/Lists/ListSlices.ptx +++ b/pretext/Lists/ListSlices.ptx @@ -5,7 +5,7 @@ that if you omit the first index (before the colon), the slice starts at the beginning of the sequence. If you omit the second index, the slice goes to the end of the sequence.

- + a_list = ['a', 'b', 'c', 'd', 'e', 'f'] print(a_list[1:3]) @@ -17,7 +17,7 @@ print(a_list[:])

Check your understanding

- +

What is printed by the following statements?

@@ -62,7 +62,7 @@ print(alist[4:]) or the rate at which it decrements (if the step size is negative). It is also possible to specify -1 as the step term to slice with the values in reverse.

- +

What is printed by the following statements?

@@ -100,7 +100,7 @@ print(alist[1:5:2])
- +

What is printed by the following statements?

diff --git a/pretext/Lists/ListValues.ptx b/pretext/Lists/ListValues.ptx index b30b2b489..3acfed0ce 100644 --- a/pretext/Lists/ListValues.ptx +++ b/pretext/Lists/ListValues.ptx @@ -22,7 +22,7 @@ Finally, there is a special list that contains no elements. It is called the empty list and is denoted [].

As you would expect, we can also assign list values to variables and pass lists as parameters to functions.

- + vocabulary = ["iteration", "selection", "control"] numbers = [17, 123] @@ -38,7 +38,7 @@ print(newlist)

Check your understanding

- +

A list can contain only integer items.

diff --git a/pretext/Lists/ListsareMutable.ptx b/pretext/Lists/ListsareMutable.ptx index d300efedf..9d3636d91 100644 --- a/pretext/Lists/ListsareMutable.ptx +++ b/pretext/Lists/ListsareMutable.ptx @@ -4,7 +4,7 @@

Unlike strings, lists are mutable. This means we can change an item in a list by accessing it directly as part of the assignment statement. Using the indexing operator (square brackets) on the left side of an assignment, we can update one of the list items.

- + fruit = ["banana", "apple", "cherry"] print(fruit) @@ -18,7 +18,7 @@ print(fruit) assignment to an element of a list is called item assignment. Item assignment does not work for strings. Recall that strings are immutable.

Here is the same example in codelens so that you can step through the statements and see the changes to the list elements.

- + fruit = ["banana", "apple", "cherry"] @@ -27,7 +27,7 @@ fruit[-1] = "orange"

By combining assignment with the slice operator we can update several elements at once.

- + alist = ['a', 'b', 'c', 'd', 'e', 'f'] alist[1:3] = ['x', 'y'] @@ -35,7 +35,7 @@ print(alist)

We can also remove elements from a list by assigning the empty list to them.

- + alist = ['a', 'b', 'c', 'd', 'e', 'f'] alist[1:3] = [] @@ -44,7 +44,7 @@ print(alist)

We can even insert elements into a list by squeezing them into an empty slice at the desired location.

- + alist = ['a', 'd', 'f'] alist[1:1] = ['b', 'c'] @@ -56,7 +56,7 @@ print(alist)

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/Lists/StringsandLists.ptx b/pretext/Lists/StringsandLists.ptx index dbe5d3d00..c3c62a75f 100644 --- a/pretext/Lists/StringsandLists.ptx +++ b/pretext/Lists/StringsandLists.ptx @@ -5,7 +5,7 @@ strings. The split method breaks a string into a list of words. By default, any number of whitespace characters is considered a word boundary.

- + song = "The rain in Spain..." wds = song.split() @@ -15,7 +15,7 @@ print(wds)

An optional argument called a delimiter can be used to specify which characters to use as word boundaries. The following example uses the string ai as the delimiter:

- + song = "The rain in Spain..." wds = song.split('ai') @@ -26,7 +26,7 @@ print(wds)

The inverse of the split method is join. You choose a desired separator string, (often called the glue) and join the list with the glue between each of the elements.

- + wds = ["red", "blue", "green"] glue = ';' @@ -43,7 +43,7 @@ print("".join(wds))

Check your understanding

- +

What is printed by the following statements?

diff --git a/pretext/Lists/listTypeConversionFunction.ptx b/pretext/Lists/listTypeConversionFunction.ptx index d3efb3713..e5e6bb786 100644 --- a/pretext/Lists/listTypeConversionFunction.ptx +++ b/pretext/Lists/listTypeConversionFunction.ptx @@ -4,7 +4,7 @@

Python has a built-in type conversion function called list that tries to turn whatever you give it into a list. For example, try the following:

- + xs = list("Crunchy Frog") print(xs) diff --git a/pretext/PythonModules/CreatingModules.ptx b/pretext/PythonModules/CreatingModules.ptx index d2843d3b0..caf5fb468 100644 --- a/pretext/PythonModules/CreatingModules.ptx +++ b/pretext/PythonModules/CreatingModules.ptx @@ -21,7 +21,7 @@ coffee_roasts = ["hot chocolate", "light", "medium", "dark", "espresso"]

This is a Python script named coffee_shop.py that contains three variables: shop_name, coffee_sizes, and coffee_roasts. The shop_name is a string, coffee_sizes is a list containing strings, and coffee_roasts is also a list containing strings.

- +

A module is another name for:

@@ -81,7 +81,7 @@ print("Available roasts:", coffee_shop.coffee_roasts) Note

The module files must be in the same directory on your computer for Python to know how to import them automatically

- +

Create a module by:

@@ -178,7 +178,7 @@ shop_says = coffee_shop.order_coffee(order_size, order_roast) print(shop_says)
- +

What determines the name of our import?

diff --git a/pretext/PythonModules/Therandommodule.ptx b/pretext/PythonModules/Therandommodule.ptx index 2b3113dd3..2b7353788 100644 --- a/pretext/PythonModules/Therandommodule.ptx +++ b/pretext/PythonModules/Therandommodule.ptx @@ -24,7 +24,7 @@

Python provides a module random that helps with tasks like this. You can take a look at it in the documentation. Here are the key things we can do with it.

- + import random @@ -50,7 +50,7 @@ print(diceThrow) the range [0.0, 5.0). Once more, these are uniformly distributed numbers — numbers close to 0 are just as likely to occur as numbers close to 0.5, or numbers close to 1.0. If you continue to press the run button you will see random values between 0.0 and up to but not including 5.0.

- + import random @@ -67,7 +67,7 @@ print(result) of the attributes of the generator) will be updated. The good news is that each time you run your program, the seed value is likely to be different meaning that even though the random numbers are being created algorithmically, you will likely get random behavior each time you execute.

- +

Check your understanding

- +

Which of the following is the correct way to reference the value pi within the math module. Assume you have already imported the math module.

@@ -119,7 +119,7 @@ print(result)
- +

Which module would you most likely use if you were writing a function to simulate rolling dice?

@@ -158,7 +158,7 @@ print(result)
- +

The correct code to generate a random number between 1 and 100 (inclusive) is:

@@ -197,7 +197,7 @@ print(result)
- +

One reason that lotteries don't use computers to generate random numbers is:

@@ -238,7 +238,7 @@ print(result)

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + diff --git a/pretext/PythonModules/modules.ptx b/pretext/PythonModules/modules.ptx index c2c896e39..68a4b6e70 100644 --- a/pretext/PythonModules/modules.ptx +++ b/pretext/PythonModules/modules.ptx @@ -7,7 +7,7 @@ Python as part of the standard library. We have already used one of these briefly, the math module. Recall that once we import the module, we can use things that are defined inside.

- + import math # allows us to use the math library @@ -51,7 +51,7 @@ print(math.sqrt(100)) # prints the square root of 100

Check your understanding

- +

In Python a module is:

@@ -90,7 +90,7 @@ print(math.sqrt(100)) # prints the square root of 100
- +

To find out information on the standard modules available with Python you should:

@@ -129,7 +129,7 @@ print(math.sqrt(100)) # prints the square root of 100
- +

True / False: All standard Python modules will work in activecode.

diff --git a/pretext/Selection/BooleanValuesandBooleanExpressions.ptx b/pretext/Selection/BooleanValuesandBooleanExpressions.ptx index fb85e1ef1..829ae3f96 100644 --- a/pretext/Selection/BooleanValuesandBooleanExpressions.ptx +++ b/pretext/Selection/BooleanValuesandBooleanExpressions.ptx @@ -8,7 +8,7 @@

There are only two boolean values. They are True and False. Capitalization is important, since true and false are not boolean values (remember Python is case sensitive).

- + print(True) print(type(True)) @@ -21,7 +21,7 @@ print(type(False)) surrounded by quotes. They are the only two values in the data type bool. Take a close look at the types shown below.

- + print(type(True)) print(type("True")) @@ -30,7 +30,7 @@ print(type("True"))

A boolean expression is an expression that evaluates to a boolean value. The equality operator, ==, compares two values and produces a boolean value related to whether the two values are equal to one another.

- + print(5 == 5) @@ -69,7 +69,7 @@ x <= y # x is less than or equal to y

Check your understanding

- +

Which of the following is a Boolean expression? Select all that apply.

diff --git a/pretext/Selection/Chainedconditionals.ptx b/pretext/Selection/Chainedconditionals.ptx index c992f9998..0f60f135b 100644 --- a/pretext/Selection/Chainedconditionals.ptx +++ b/pretext/Selection/Chainedconditionals.ptx @@ -25,7 +25,7 @@ else: statement ends. Even if more than one condition is true, only the first true branch executes.

Here is the same program using elif.

- + x = 10 y = 10 @@ -40,7 +40,7 @@ else:

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -50,7 +50,7 @@ else:

Check your understanding

- +

Which of I, II, and III below gives the same result as the following nested if?

diff --git a/pretext/Selection/ConditionalExecutionBinarySelection.ptx b/pretext/Selection/ConditionalExecutionBinarySelection.ptx index 1f27e656a..19c82b6b9 100644 --- a/pretext/Selection/ConditionalExecutionBinarySelection.ptx +++ b/pretext/Selection/ConditionalExecutionBinarySelection.ptx @@ -6,7 +6,7 @@ conditions and change the behavior of the program accordingly. Branching statements, sometimes also referred to as conditional statements or Selection statements, give us this ability. The simplest form of branching is the if statement. This is sometimes referred to as binary selection since there are two possible paths of execution.

- + x = 15 @@ -78,7 +78,7 @@ else:

Check your understanding

- +

How many statements can appear in each block (the if and the else) in a conditional statement?

@@ -117,7 +117,7 @@ else:
- +

What does the following code print (choose from output a, b, c or nothing)?

@@ -164,7 +164,7 @@ else:
- +

What does the following code print?

diff --git a/pretext/Selection/ListMembership.ptx b/pretext/Selection/ListMembership.ptx index 5a3390b01..d0947ef96 100644 --- a/pretext/Selection/ListMembership.ptx +++ b/pretext/Selection/ListMembership.ptx @@ -1,9 +1,9 @@ -
+
List Membership

in and not in are boolean operators that test membership in a sequence. We used them previously with strings and they also work here.

- + fruit = ["apple", "orange", "banana", "cherry"] @@ -14,7 +14,7 @@ print("pear" in fruit)

Check your understanding

- +

What is printed by the following statements?

@@ -43,7 +43,7 @@ print(3.14 in alist)
- +

What is printed by the following statements?

diff --git a/pretext/Selection/Logicaloperators.ptx b/pretext/Selection/Logicaloperators.ptx index 61a4c5da4..0e2fa8931 100644 --- a/pretext/Selection/Logicaloperators.ptx +++ b/pretext/Selection/Logicaloperators.ptx @@ -13,7 +13,7 @@

Finally, the not operator negates a boolean expression, so not x > y is true if x > y is false, that is, if x is less than or equal to y.

- + x = 5 print(x > 0 and x < 10) @@ -222,12 +222,12 @@ print(n % 2 == 0 or n % 3 == 0) -

Also, Google has provided this short video showing different logical operators:

+ WARNING!

There is a very common mistake that occurs when programmers try to write boolean expressions. For example, what if we have a variable number and we want to check to see if its value is 5,6, or 7. In words we might say: number equal to 5 or 6 or 7. However, if we translate this into Python, number == 5 or 6 or 7, it will not be correct. The or operator must join the results of three equality checks. The correct way to write this is number == 5 or number == 6 or number == 7. This may seem like a lot of typing but it is absolutely necessary. You cannot take a shortcut.

@@ -235,7 +235,7 @@ print(n % 2 == 0 or n % 3 == 0)

Check your understanding

- +

What is a correct Python expression for checking to see if a number stored in a variable x is between 0 and 5?

@@ -266,7 +266,7 @@ print(n % 2 == 0 or n % 3 == 0)
- +

Say you are registering for next semester's classes. You have choice A, which is your art class, and choice B, which is your math class. You need both of them, but it's a race between time and luck. If you end up registering on time for choice A, but you don't get your choice B, which logical operators would be true?

diff --git a/pretext/Selection/Nestedconditionals.ptx b/pretext/Selection/Nestedconditionals.ptx index ba25f525d..32fb7047e 100644 --- a/pretext/Selection/Nestedconditionals.ptx +++ b/pretext/Selection/Nestedconditionals.ptx @@ -21,7 +21,7 @@ else:

The flow of control for this example can be seen in this flowchart illustration.

Here is a complete program that defines values for x and y. Run the program and see the result. Then change the values of the variables to change the flow of control.

- + x = 10 y = 10 @@ -41,7 +41,7 @@ else: belongs to which if.

If you are still a bit unsure, here is the same selection as part of a codelens example. Step through it to see how the correct print is chosen.

- + x = 10 y = 10 @@ -58,7 +58,7 @@ else:

Check your understanding

- +

Will the following code cause an error?

diff --git a/pretext/Selection/OmittingtheelseClauseUnarySelection.ptx b/pretext/Selection/OmittingtheelseClauseUnarySelection.ptx index 22fc45a44..98f7cae36 100644 --- a/pretext/Selection/OmittingtheelseClauseUnarySelection.ptx +++ b/pretext/Selection/OmittingtheelseClauseUnarySelection.ptx @@ -10,7 +10,7 @@ This creates what is sometimes called unary selection. In this case, when the condition evaluates to True, the statements are executed. Otherwise the flow of execution continues to the statement after the body of the if.

- + x = 10 if x < 0: @@ -22,7 +22,7 @@ print("This is always printed")

Check your understanding

- +

What does the following code print?

@@ -78,7 +78,7 @@ The negative number -10 is not valid here
- +

Will the following code cause an error?

diff --git a/pretext/Selection/PrecedenceofOperators.ptx b/pretext/Selection/PrecedenceofOperators.ptx index 157960858..4be2eb701 100644 --- a/pretext/Selection/PrecedenceofOperators.ptx +++ b/pretext/Selection/PrecedenceofOperators.ptx @@ -98,7 +98,7 @@

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

- + @@ -108,7 +108,7 @@

Check your understanding

- +

Which of the following properly expresses the precedence of operators (using parentheses) in the following expression: 5*3 > 10 and 4+6==11

diff --git a/pretext/Selection/StringComparison.ptx b/pretext/Selection/StringComparison.ptx index 18e900be0..377dffd26 100644 --- a/pretext/Selection/StringComparison.ptx +++ b/pretext/Selection/StringComparison.ptx @@ -1,9 +1,9 @@ -
+
String Comparison

The comparison operators also work on strings. To see if two strings are equal you simply write a boolean expression using the equality operator.

- + word = "banana" if word == "banana": @@ -16,7 +16,7 @@ else: lexicographical order. This is similar to the alphabetical order you would use with a dictionary, except that all the uppercase letters come before all the lowercase letters.

- + word = "zebra" @@ -31,7 +31,7 @@ else:

It is probably clear to you that the word apple would be less than (come before) the word banana. After all, a is before b in the alphabet. But what if we consider the words apple and Apple? Are they the same?

- + print("apple" < "banana") @@ -42,7 +42,7 @@ print("apple" < "Apple")

It turns out, as you recall from our discussion of variable names, that uppercase and lowercase letters are considered to be different from one another. The way the computer knows they are different is that each character is assigned a unique integer value. A is 65, B is 66, and 5 is 53. The way you can find out the so-called ordinal value for a given character is to use a character function called ord.

- + print(ord("A")) print(ord("B")) @@ -56,7 +56,7 @@ print("apple" > "Apple")

Humans commonly ignore capitalization when comparing two words. However, computers do not. A common way to address this issue is to convert strings to a standard format, such as all lowercase, before performing the comparison.

There is also a similar function called chr that converts integers into their character equivalent.

- + print(chr(65)) print(chr(66)) @@ -72,7 +72,7 @@ print(ord(" "))

Check your understanding

- +

Evaluate the following comparison:

@@ -100,7 +100,7 @@ print(ord(" "))
- +

Evaluate the following comparison:

@@ -136,7 +136,7 @@ print(ord(" "))
- +

Evaluate the following comparison:

diff --git a/pretext/Selection/Theinandnotinoperators.ptx b/pretext/Selection/Theinandnotinoperators.ptx index 72b360b84..771621981 100644 --- a/pretext/Selection/Theinandnotinoperators.ptx +++ b/pretext/Selection/Theinandnotinoperators.ptx @@ -1,8 +1,8 @@ -
+
The <c>in</c> and <c>not in</c> operators

The in operator tests if one string is a substring of another:

- + print('p' in 'apple') print('i' in 'apple') @@ -13,7 +13,7 @@ print('pa' in 'apple')

Note that a string is a substring of itself, and the empty string is a substring of any other string. (Also note that computer scientists like to think about these edge cases quite carefully!)

- + print('a' in 'a') print('apple' in 'apple') @@ -22,7 +22,7 @@ print('' in 'apple')

The not in operator returns the logical opposite result of in.

- + print('x' not in 'apple') diff --git a/pretext/SimplePythonData/Input.ptx b/pretext/SimplePythonData/Input.ptx index d3cc2f98e..c3788c922 100644 --- a/pretext/SimplePythonData/Input.ptx +++ b/pretext/SimplePythonData/Input.ptx @@ -1,7 +1,7 @@
Input -

For more information consult the string module documentation (see Global Module Index).

- + +More About ASCII +

ASCII is abbreviated from American Standard Code for Information Interchange. As computers store data in numeric values, for each character (words, punctuations, etc) a specific number is assigned to represent it. This process is called character encoding. In order to exchange informations between different computers, a set of standards were needed, from which ASCII was born.

+

ASCII contains 128 characters, where each character is assigned with a specific number. For instance uppercase alphabet starts from A = 65, while lowercase alphabet starts from a = 97 and continues as b=98, c=99, so on. Due to its limited size, this standard is replaced by Unicode which contains thousands of characters, however still useful to understand and work on encoding.

+ +
+ + + + +

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

From cc901a9d9d120a9489044066e29c83de0444e11d Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:18:48 -0600 Subject: [PATCH 56/90] Update StringComparison.ptx added more info about encoding --- pretext/Selection/StringComparison.ptx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretext/Selection/StringComparison.ptx b/pretext/Selection/StringComparison.ptx index 377dffd26..1fdb4b30a 100644 --- a/pretext/Selection/StringComparison.ptx +++ b/pretext/Selection/StringComparison.ptx @@ -40,7 +40,7 @@ print("apple" < "Apple")

It turns out, as you recall from our discussion of variable names, that uppercase and lowercase letters are considered to be different from one another. The way the computer knows they are different is that - each character is assigned a unique integer value. A is 65, B is 66, and 5 is 53. The way you can + each character is assigned a unique integer value which is called character encoding, as you may recall from Character Classification section. For instance, A is 65, B is 66, a is 97, b is 98 and 5 is 53. The way you can find out the so-called ordinal value for a given character is to use a character function called ord.

From a42c6b9afcf98f946326a4fb218f9e30fd532303 Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:59:54 -0600 Subject: [PATCH 57/90] Add files via upload summary removed --- pretext/Debugging/toctree.ptx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pretext/Debugging/toctree.ptx b/pretext/Debugging/toctree.ptx index 2f03e1bcc..5e66dcaed 100644 --- a/pretext/Debugging/toctree.ptx +++ b/pretext/Debugging/toctree.ptx @@ -1,9 +1,15 @@ -4Debugging Interlude -4 -4 -4 -4 -4 +4Strings +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 +4 From 8e7a397a71572a77d1b9a004daddf8586058d999 Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:03:41 -0600 Subject: [PATCH 58/90] Update toctree.ptx summary removed --- pretext/Strings/toctree.ptx | 1 - 1 file changed, 1 deletion(-) diff --git a/pretext/Strings/toctree.ptx b/pretext/Strings/toctree.ptx index d9088bc14..5e66dcaed 100644 --- a/pretext/Strings/toctree.ptx +++ b/pretext/Strings/toctree.ptx @@ -11,6 +11,5 @@ 4 4 4 -4 4 From 9ab17af28ac74faedbd5da6c8d3e9f2f04a7d407 Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:05:38 -0600 Subject: [PATCH 59/90] Update toctree.ptx false update corrected --- pretext/Debugging/toctree.ptx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/pretext/Debugging/toctree.ptx b/pretext/Debugging/toctree.ptx index 5e66dcaed..2f03e1bcc 100644 --- a/pretext/Debugging/toctree.ptx +++ b/pretext/Debugging/toctree.ptx @@ -1,15 +1,9 @@ -4Strings -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 +4Debugging Interlude +4 +4 +4 +4 +4 From d87dddebef4255c677e3a07923c3d4e5d368b590 Mon Sep 17 00:00:00 2001 From: metesaka <61266931+metesaka@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:06:23 -0600 Subject: [PATCH 60/90] Update KnowyourerrorMessages.ptx errors fixed on hints and exercises --- pretext/Debugging/KnowyourerrorMessages.ptx | 514 +++++++++++--------- 1 file changed, 271 insertions(+), 243 deletions(-) diff --git a/pretext/Debugging/KnowyourerrorMessages.ptx b/pretext/Debugging/KnowyourerrorMessages.ptx index fe9e333d1..8518fd9b0 100644 --- a/pretext/Debugging/KnowyourerrorMessages.ptx +++ b/pretext/Debugging/KnowyourerrorMessages.ptx @@ -1,25 +1,31 @@
Know Your Error Messages - -

Many problems in your program will lead to an error message. For example as I was writing and testing this chapter of the book I wrote the following version of the example program in the previous section.

-
+ + +

Many problems in your program will lead to an error message. For example as I was writing and testing this chapter of the book I wrote the following version of the example program in the previous section.

+ - + + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") current_time_int = int(current_time_str) wait_time_int = int(wait_time_int) + final_time_int = current_time_int + wait_time_int print(final_time_int) + +

Can you see what is wrong, just by looking at the code? Maybe, maybe not. Our brain tends to see what we think is there, so sometimes it is very hard to find the problem just by looking at the code. Especially when it is our own code and we are sure that we have done everything right!

Let's try the program again, but this time in an activecode:

- - + + + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") @@ -28,227 +34,226 @@ wait_time_int = int(wait_time_int) final_time_int = current_time_int + wait_time_int print(final_time_int) - + +

Aha! Now we have an error message that might be useful. The name error tells us that wait_time_int is not defined. It also tells us that the error is on line 5. That's really useful information. Now look at line five and you will see that wait_time_int is used on both the left and the right hand side of the assignment statement.

+ -

The error descriptions you see in activecode may be different (and more understandable!) than in a regular - Python interpreter. The interpreter in activecode is limited in many ways, but it is intended for beginners, - including the wording chosen to describe errors.

+

The error descriptions you see in activecode may be different (and more understandable!) than in a regular + Python interpreter. The interpreter in activecode is limited in many ways, but it is intended for beginners, + including the wording chosen to describe errors.

+ - -

Which of the following explains why wait_time_int = int(wait_time_int) is an error?

-
- - - -

You cannot use a variable on both the left and right hand sides of an assignment statement.

-
- - No, You can, as long as all the variables on the right hand side already have values. - -
- - -

wait_time_int does not have a value so it cannot be used on the right hand side.

-
- - Yes. Variables must already have values in order to be used on the right hand side. - -
- - -

This is not really an error, Python is broken.

-
- - No, No, No! - -
-
+ +

Which of the following explains why wait_time_int = int(wait_time_int) is an error?

+
+ + + +

You cannot use a variable on both the left and right hand sides of an assignment statement.

+
+ + No, You can, as long as all the variables on the right hand side already have values. + +
+ + +

wait_time_int does not have a value so it cannot be used on the right hand side.

+
+ + Yes. Variables must already have values in order to be used on the right hand side. + +
+ + +

This is not really an error, Python is broken.

+
+ + No, No, No! + +
+
+

In writing and using this book over the last few years we have collected a lot of statistics about the programs in this book. Here are some statistics about error messages for the exercise we have been looking at.

- - - - Message - - - Number - - - Percent - - - - - ParseError: - - - 4999 - - - 54.74% - - - - - TypeError: - - - 1305 - - - 14.29% - - - - - NameError: - - - 1009 - - - 11.05% - - - - - ValueError: - - - 893 - - - 9.78% - - - - - URIError: - - - 334 - - - 3.66% - - - - - TokenError: - - - 244 - - - 2.67% - - - - - SyntaxError: - - - 227 - - - 2.49% - - - - - TimeLimitError: - - - 44 - - - 0.48% - - - - - IndentationError: - - - 28 - - - 0.31% - - - - - AttributeError: - - - 27 - - - 0.30% - - - - - ImportError: - - - 16 - - - 0.18% - - - - - IndexError: - - - 6 - - - 0.07% - - - + + + + Message + + + Number + + + Percent + + + + + ParseError: + + + 4999 + + + 54.74% + + + + + TypeError: + + + 1305 + + + 14.29% + + + + + NameError: + + + 1009 + + + 11.05% + + + + + ValueError: + + + 893 + + + 9.78% + + + + + URIError: + + + 334 + + + 3.66% + + + + + TokenError: + + + 244 + + + 2.67% + + + + + SyntaxError: + + + 227 + + + 2.49% + + + + + TimeLimitError: + + + 44 + + + 0.48% + + + + + IndentationError: + + + 28 + + + 0.31% + + + + + AttributeError: + + + 27 + + + 0.30% + + + + + ImportError: + + + 16 + + + 0.18% + + + + + IndexError: + + + 6 + + + 0.07% + + +
+

Nearly 90% of the error messages encountered for this problem are ParseError, TypeError, NameError, or ValueError. We will look at these errors in three stages:

-

    -
  • -

    First we will define what these four error messages mean.

    -
  • -
  • -

    Then, we will look at some examples that cause these errors to occur.

    -
  • -
  • -

    Finally we will look at ways to help uncover the root cause of these messages.

    -
  • -
+
    +
  • +

    First we will define what these four error messages mean.

    +
  • +
  • +

    Then, we will look at some examples that cause these errors to occur.

    +
  • +
  • +

    Finally we will look at ways to help uncover the root cause of these messages.

    +
  • +

+ +
+ ParseError

Parse errors happen when you make an error in the syntax of your program. Syntax errors are like making grammatical errors in writing. If you don't use periods and commas in your writing then you are making it hard for other readers to figure out what you are trying to say. Similarly Python has certain grammatical rules that must be followed or else Python can't figure out what you are trying to say.

-

Usually ParseErrors can be traced back to missing punctuation characters, such as parentheses, quotation marks, or commas. Remember that in Python commas are used to separate parameters to functions. Parentheses must be balanced, or else Python thinks that you are trying to include everything that follows as a parameter to some function.

+ +

Usually ParseErrors can be traced back to missing punctuation characters, such as parentheses, quotation marks, or commas. Remember that in Python commas are used to separate values, such as when defining a list or giving multiple values to a function call. Parentheses must be balanced, or else Python thinks that you are trying to include everything that follows as a parameter to some function.

Here are a couple examples of Parse errors in the example program we have been using. See if you can figure out what caused them.

- - - - - current_time_str = input("What is the current time (in hours 0-23)?") -wait_time_str = input("How many hours do you want to wait" -current_time_int = int(current_time_str) -wait_time_int = int(wait_time_str) + -final_time_int = current_time_int + wait_time_int -print(final_time_int) - Since the error message points us to line 4 this might be a bit confusing. If you look at line four carefully you will see that there is no problem with the syntax. So, in this case the next step should be to back up and look at the previous line. In this case if you look at line 2 carefully you will see that there is a missing right parenthesis at the end of the line. Remember that parenthses must be balanced. Since Python allows statements to continue over multiple lines inside parentheses Python will continue to scan subsequent lines looking for the balancing right parenthesis. However in this case it finds the name current_time_int and it will want to interpret that as another parameter to the input function. But, there is not a comma to separate the previous string from the variable so as far as Python is concerned the error here is a missing comma. From your perspective its a missing parenthesis. - - + + current_time_str = input("What is the current time (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait" @@ -258,25 +263,23 @@ wait_time_int = int(wait_time_str) final_time_int = current_time_int + wait_time_int print(final_time_int) -

Since the error message points us to line 4 this might be a bit confusing. If you look at line four carefully you will see that there is no problem with the syntax. So, in this case the next step should be to back up and look at the previous line. In this case if you look at line 2 carefully you will see that there is a missing right parenthesis at the end of the line. Remember that parenthses must be balanced. Since Python allows statements to continue over multiple lines inside parentheses Python will continue to scan subsequent lines looking for the balancing right parenthesis. However in this case it finds the name current_time_int and it will want to interpret that as another parameter to the input function. But, there is not a comma to separate the previous string from the variable so as far as Python is concerned the error here is a missing comma. From your perspective its a missing parenthesis.

-
-
-

Finding Clues How can you help yourself find these problems? One trick that can be very valuable in this situation is to simply start by commenting out the line number that is flagged as having the error. If you comment out line four, the error message now changes to point to line 5. Now you ask yourself, am I really that bad that I have two lines in a row that have errors on them? Maybe, so taken to the extreme, you could comment out all of the remaining lines in the program. Now the error message changes to TokenError: EOF in multi-line statement This is a very technical way of saying that Python got to the end of file (EOF) while it was still looking for something. In this case a right parenthesis.

- - - - - current_time_str = input("What is the "current time" (in hours 0-23)?") -wait_time_str = input("How many hours do you want to wait") -current_time_int = int(current_time_str) -wait_time_int = int(wait_time_str) -final_time_int = current_time_int + wait_time_int -print(final_time_int) - The error message points you to line 1 and in this case that is exactly where the error occurs. In this case your biggest clue is to notice the difference in highlighting on the line. Notice that the words current time are a different color than those around them. Why is this? Because current time is in double quotes inside another pair of double quotes Python thinks that you are finishing off one string, then you have some other names and finally another string. But you haven't separated these names or strings by commas, and you haven't added them together with the concatenation operator (+). So, there are several corrections you could make. First you could make the argument to input be as follows: "What is the 'current time' (in hours 0-23)" Notice that here we have correctly used single quotes inside double quotes. Another option is to simply remove the extra double quotes. Why were you quoting current time anyway? "What is the current time (in hours 0-23)" - - + +

+ Since the error message points us to line 4 this might be a bit confusing. If you look at line four carefully you will see that there is no problem with the syntax. So, in this case the next step should be to back up and look at the previous line. In this case if you look at line 2 carefully you will see that there is a missing right parenthesis at the end of the line. Remember that parentheses must be balanced. Since Python allows statements to continue over multiple lines inside parentheses Python will continue to scan subsequent lines looking for the balancing right parenthesis. However in this case it finds the name current_time_int and it will want to interpret that as another parameter to the input function. But, there is not a comma to separate the previous string from the variable so as far as Python is concerned the error here is a missing comma. From your perspective its a missing parenthesis. +

+ + +
+ +
+ +

Finding Clues How can you help yourself find these problems? One trick that can be very valuable in this situation is to simply start by commenting out the line number that is flagged as having the error. If you comment out line four, the error message now changes to point to line 5. Now you ask yourself, am I really that bad that I have two lines in a row that have errors on them? Maybe, so taken to the extreme, you could comment out all of the remaining lines in the program. Now the error message changes to TokenError: EOF in multi-line statement This is a very technical way of saying that Python got to the end of file (EOF) while it was still looking for something. In this case a right parenthesis.

+ + + + current_time_str = input("What is the "current time" (in hours 0-23)?") wait_time_str = input("How many hours do you want to wait") @@ -286,16 +289,25 @@ wait_time_int = int(wait_time_str) final_time_int = current_time_int + wait_time_int print(final_time_int) -

The error message points you to line 1 and in this case that is exactly where the error occurs. In this case your biggest clue is to notice the difference in highlighting on the line. Notice that the words current time are a different color than those around them. Why is this? Because current time is in double quotes inside another pair of double quotes Python thinks that you are finishing off one string, then you have some other names and finally another string. But you haven't separated these names or strings by commas, and you haven't added them together with the concatenation operator (+). So, there are several corrections you could make. First you could make the argument to input be as follows: "What is the 'current time' (in hours 0-23)" Notice that here we have correctly used single quotes inside double quotes. Another option is to simply remove the extra double quotes. Why were you quoting current time anyway? "What is the current time (in hours 0-23)"

- + + +

+ The error message points you to line 1 and in this case that is exactly where the error occurs. In this case your biggest clue is to notice the difference in highlighting on the line. Notice that the words current time are a different color than those around them. Why is this? Because current time is in double quotes inside another pair of double quotes Python thinks that you are finishing off one string, then you have some other names and finally another string. But you haven't separated these names or strings by commas, and you haven't added them together with the concatenation operator (+). So, there are several corrections you could make. First you could make the argument to input be as follows: "What is the 'current time' (in hours 0-23)" Notice that here we have correctly used single quotes inside double quotes. Another option is to simply remove the extra double quotes. Why were you quoting current time anyway? "What is the current time (in hours 0-23)" +

+ +
+ +

Finding Clues If you follow the same advice as for the last problem, comment out line one, you will immediately get a different error message. Here's where you need to be very careful and not panic. The error message you get now is: NameError: name 'current_time_str' is not defined on line 4. You might be very tempted to think that this is somehow related to the earlier problem and immediately conclude that there is something wrong with the variable name current_time_str but if you reflect for a minute you will see that by commenting out line one you have caused a new and unrelated error. That is you have commented out the creation of the name current_time_str. So of course when you want to convert it to an int you will get the NameError. Yes, this can be confusing, but it will become much easier with experience. It's also important to keep calm, and evaluate each new clue carefully so you don't waste time chasing problems that are not really there.

Uncomment line 1 and you are back to the ParseError. Another track is to eliminate a possible source of error. Rather than commenting out the entire line you might just try to assign current_time_str to a constant value. For example you might make line one look like this: current_time_str = "10" #input("What is the "current time" (in hours 0-23)?"). Now you have assigned current_time_str to the string 10, and commented out the input statement. And now the program works! So you conclude that the problem must have something to do with the input function.

+ TypeError

TypeErrors occur when you you try to combine two objects that are not compatible. For example you try to add together an integer and a string. Usually type errors can be isolated to lines that are using mathematical operators, and usually the line number given by the error message is an accurate indication of the line.

Here's an example of a type error created by a Polish learner. See if you can find and fix the error.

+ a = input('wpisz godzine') @@ -310,8 +322,7 @@ print ('godzina teraz', a) - - Solution +

In finding this error there are few lessons to think about. First, you may find it very disconcerting that you cannot understand the whole program. Unless you speak Polish then this won't be an issue. But, learning what you can ignore, and what you need to focus on is a very important part of the debugging process. Second, types and good variable names are important and can be very helpful. In this case a and x are not particularly helpful names, and in particular they do not help you think about the types of your variables, which as the error message implies is the root of the problem here. The rest of the lessons we will get back to in a minute.

The error message provided to you gives you a pretty big hint. TypeError: unsupported operand type(s) for FloorDiv: 'str' and 'number' on line: 5 On line five we are trying to use integer division on x and 24. The error message tells you that you are tyring to divide a string by a number. In this case you know that 24 is a number so x must be a string. But how? You can see the function call on line 3 where you are converting x to an integer. int(x) or so you think. This is lesson three and is one of the most common errors we see in introductory programming. What is the difference between int(x) and x = int(x)

@@ -325,14 +336,20 @@ print ('godzina teraz', a)

So, the solution to this problem is to change lines 3 and 4 so they are assignment statements.

-
+
+

Finding Clues One thing that can help you in this situation is to print out the values and the types of the variables involved in the statement that is causing the error. You might try adding a print statement after line 4 print(x, type(x)) You will see that at least we have confirmed that x is of type string. Now you need to start to work backward through the program. You need to ask yourself, where is x used in the program? x is used on lines 2, 3, and of course 5 and 6 (where we are getting an error). So maybe you move the print statement to be after line 2 and again after 3. Line 3 is where you expect the value of x to be changed to an integer. Could line 4 be mysteriously changing x back to a string? Not very likely. So the value and type of x is just what you would expect it to be after line 2, but not after line 3. This helps you isolate the problem to line 3. In fact if you employ one of our earlier techniques of commenting out line 3 you will see that this has no impact on the error, and is a big clue that line 3 as it is currently written is useless.

+ + + NameError

Name errors almost always mean that you have used a variable before it has a value. Often NameErrors are simply caused by typos in your code. They can be hard to spot if you don't have a good eye for catching spelling mistakes. Other times you may simply mis-remember the name of a variable or even a function you want to call. You have seen one example of a NameError at the beginning of this section. Here is another one. See if you can get this program to run successfully:

- + + + str_time = input("What time is it now?") str_wait_time = input("What is the number of nours to wait?") @@ -344,11 +361,15 @@ print(time_when_alarm_go_off) - - Solution + +

In this example, the student seems to be a fairly bad speller, as there are a number of typos to fix. The first one is identified as wait_time is not defined on line 6. Now in this example you can see that there is str_wait_time on line 2, and wai_time on line 4 and wait_time on line 6. If you do not have very sharp eyes its easy to miss that there is a typo on line 4.

-
+
+
+ + +

Finding Clues With name errors one of the best things you can do is use the editor, or browser search function. Quite often if you search for the exact word in the error message one of two things will happen:

    @@ -361,6 +382,7 @@ print(time_when_alarm_go_off)

Here is another one for you to try:

+ n = input("What time is it now (in hours)?") @@ -371,25 +393,29 @@ q = m % 12 print("The time is now", q) + + - - Solution +

This one is once again a typo, but the typo is not in a variable name, but rather, the name of a function. The search strategy would help you with this one easily, but there is another clue for you as well. The editor in the textbook, as well as almost all Python editors in the world provide you with color clues. Notice that on line 2 the function imt is not highlighted blue like the word int on line 4.

-
-
+ +
+

And one last bit of code to fix.

+ -present_time = input("Enter the present timein hours:") +present_time = input("Enter the present time in hours:") set_alarm = input("Set the hours for alarm:") int (present_time, set_time, alarm_time) alarm_time = present_time + set_alarm print(alarm_time) + + + - - Solution

In this example the error message is about set_time not defined on line 3. In this case the undefined name is not used in an assignment statement, but is used as a parameter (incorrectly) to a function call. A search on set_time reveals that in fact it is only used once in the program. Did the author mean set_alarm? If we make that assumption we immediately get another error NameError: name 'alarm_time' is not defined on line: 3. The variable alarm_time is defined on line 4, but that does not help us on line 3. Furthermore we now have to ask the question is this function call int(present_time, set_alarm, alarm_time) even the correct use of the int function? The answer to that is a resounding no. Let's list all of the things wrong with line 3:

    @@ -407,8 +433,8 @@ print(alarm_time)

-
+
@@ -419,9 +445,11 @@ print(alarm_time)
+ ValueError

Value errors occur when you pass a parameter to a function and the function is expecting a certain limitations on the values, and the value passed is not compatible. We can illustrate that with this particular program in two different ways.

+ current_time_str = input("What is the current time (in hours 0-23)?") From a951fe16470189be45a291afb9c959138fb1778e Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 13 Jul 2023 11:57:16 -0600 Subject: [PATCH 61/90] Expanded Last Chapter Moved dictionary sections into the additional topics chapter, as well as made a new section on dictionary comprehensions. --- .../AdditionalTopics/Aliasingandcopying.ptx | 78 +++ .../DictionaryComprehensions.ptx | 91 +++ .../AdditionalTopics/Dictionarymethods.ptx | 365 ++++++++++++ .../AdditionalTopics/Dictionaryoperations.ptx | 88 +++ pretext/AdditionalTopics/Exercises.ptx | 532 ++++++++++++++++++ pretext/AdditionalTopics/Glossary.ptx | 33 ++ .../AdditionalTopics/ListComprehensions.ptx | 12 +- .../AdditionalTopics/intro-Dictionaries.ptx | 139 +++++ pretext/AdditionalTopics/toctree.ptx | 6 + 9 files changed, 1341 insertions(+), 3 deletions(-) create mode 100644 pretext/AdditionalTopics/Aliasingandcopying.ptx create mode 100644 pretext/AdditionalTopics/DictionaryComprehensions.ptx create mode 100644 pretext/AdditionalTopics/Dictionarymethods.ptx create mode 100644 pretext/AdditionalTopics/Dictionaryoperations.ptx create mode 100644 pretext/AdditionalTopics/Exercises.ptx create mode 100644 pretext/AdditionalTopics/Glossary.ptx create mode 100644 pretext/AdditionalTopics/intro-Dictionaries.ptx diff --git a/pretext/AdditionalTopics/Aliasingandcopying.ptx b/pretext/AdditionalTopics/Aliasingandcopying.ptx new file mode 100644 index 000000000..97a0c7c0e --- /dev/null +++ b/pretext/AdditionalTopics/Aliasingandcopying.ptx @@ -0,0 +1,78 @@ + +
+ Aliasing and Copying +

Because dictionaries are mutable, you need to be aware of aliasing (as we saw with lists). Whenever + two variables refer to the same dictionary object, changes to one affect the other. + For example, opposites is a dictionary that contains pairs + of opposites.

+ + +opposites = {'up': 'down', 'right': 'wrong', 'true': 'false'} +alias = opposites + +print(alias is opposites) + +alias['right'] = 'left' +print(opposites['right']) + + +

As you can see from the is operator, alias and opposites refer to the same object.

+

If you want to modify a dictionary and keep a copy of the original, use the dictionary + copy method. Since acopy is a copy of the dictionary, changes to it will not effect the original.

+ + +acopy = opposites.copy() +acopy['right'] = 'left' # does not change opposites + + +

+ Check your understanding +

+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +yourdict = mydict +yourdict["elephant"] = 999 +print(mydict["elephant"]) + + +
+ + + +

23

+
+ + mydict and yourdict are both names for the same dictionary. + +
+ + +

None

+
+ + The dictionary is mutable so changes can be made to the keys and values. + +
+ + +

999

+
+ + Yes, since yourdict is an alias for mydict, the value for the key elephant has been changed. + +
+ + +

Error, there are two different keys named elephant.

+
+ + There is only one dictionary with only one key named elephant. The dictionary has two different names, mydict and yourdict. + +
+
+
+
diff --git a/pretext/AdditionalTopics/DictionaryComprehensions.ptx b/pretext/AdditionalTopics/DictionaryComprehensions.ptx new file mode 100644 index 000000000..21d295a30 --- /dev/null +++ b/pretext/AdditionalTopics/DictionaryComprehensions.ptx @@ -0,0 +1,91 @@ + +
+ Dictionary Comprehensions +

Like lists, dictionaries also support comprehensions as an alternative to dictionary generation with lengthier loops. The format for a dictionary comprehension is as follows

+
{<key-expression>:<value-expression> for <item> in <sequence> if <condition>}
+

Make careful note of the use of curly brackets instead of square brackets. These brackets are primarily how Python determines what kind of comprehension + you are making. Like list comprehensions, the if clause is optional.

+

Let's view an example,

+ + +first_names = ["Radia", "Grace", "Katherine", "Jeannette"] +last_names = ["Perlman", "Hopper", "Johnson", "Wing"] + +first_to_last = {first_names[i]:last_names[i] for i in range(len(first_names))} + +print(first_to_last) + + +

This code takes two separate lists and associates their values in a new dictionary. More specifically, first names are mapped to last names.

+

Another more complicated example:

+ + +def percentage(n): + """ Return a percentage value from a provided raw score, rounded to two decimal places. """ + + return round((n / 1000) * 100, 2) + +names = ["Sansa", "Jamie", "Cersei", "Jon", "Arya"] +percentage_scores = {name:percentage(int(input(f"Please enter a score for {name}"))) for name in names} +print(percentage_scores) + + + +

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

+ + + + + + +
+

+ Check your understanding +

+ + +

What is printed by the following statements?

+ + +alist = [4,2,8,6,5] +dic = {num:num**2 for num in alist if num < 6} +print(dic) + + +
+ + + +

[4,2,5]

+
+ + This is the list of keys that will be generated, but it is missing the associated values. + +
+ + +

{4:16,2:4,8:64,6:36,5:25}

+
+ + This is nearly correct, but has too many values. Look at the if clause. + +
+ + +

{4:16,2:4,5:25}

+
+ + Yes, this is correct. + +
+ + +

{4:8,2:4,5:10}

+
+ + These are the correct keys, but pay close attention to the value expression in the code. + +
+
+
+
diff --git a/pretext/AdditionalTopics/Dictionarymethods.ptx b/pretext/AdditionalTopics/Dictionarymethods.ptx new file mode 100644 index 000000000..c1455c0bf --- /dev/null +++ b/pretext/AdditionalTopics/Dictionarymethods.ptx @@ -0,0 +1,365 @@ + +
+ Dictionary Methods +

Dictionaries have a number of useful built-in methods. + The following table provides a summary and more details can be found in the + Python Documentation.

+ + + + + Method + + + Parameters + + + Description + + + + + keys + + + none + + + Returns a view of the keys in the dictionary + + + + + values + + + none + + + Returns a view of the values in the dictionary + + + + + items + + + none + + + Returns a view of the key-value pairs in the dictionary + + + + + get + + + key + + + Returns the value associated with key; None otherwise + + + + + get + + + key,alt + + + Returns the value associated with key; alt otherwise + + + +
+

The keys method returns what Python 3 calls a view of its underlying keys. + We can iterate over the view or turn the view into a + list by using the list conversion function.

+ + +inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + +for akey in inventory.keys(): # the order in which we get the keys is not defined + print("Got key", akey, "which maps to value", inventory[akey]) + +ks = list(inventory.keys()) +print(ks) + + +

It is so common to iterate over the keys in a dictionary that you can + omit the keys method call in the for loop — iterating over + a dictionary implicitly iterates over its keys.

+ + +inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + +for k in inventory: + print("Got key", k) + + +

As we saw earlier with strings and lists, dictionary methods use dot notation, + which specifies the name of the method to the right of the dot and the name of + the object on which to apply the method immediately to the left of the dot. The empty + parentheses in the case of keys indicate that this method takes no parameters.

+

The values and items methods are similar to keys. They return view objects which can be turned + into lists or iterated over directly. Note that the items are shown as tuples containing the key and the associated value.

+ + +inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + +print(list(inventory.values())) +print(list(inventory.items())) + +for (k,v) in inventory.items(): + print("Got", k, "that maps to", v) + +for k in inventory: + print("Got", k, "that maps to", inventory[k]) + + +

Note that tuples are often useful for getting both the key and the value at the same + time while you are looping. The two loops do the same thing.

+

The in and not in operators can test if a key is in the dictionary:

+ + +inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} +print('apples' in inventory) +print('cherries' in inventory) + +if 'bananas' in inventory: + print(inventory['bananas']) +else: + print("We have no bananas") + + +

This operator can be very useful since looking up a non-existent key in a + dictionary causes a runtime error.

+

The get method allows us to access the value associated with a key, similar to the [ ] operator. + The important difference is that get will not cause a runtime error if the key is not present. It + will instead return None. There exists a variation of get that allows a second parameter that serves as an alternative return value + in the case where the key is not present. This can be seen in the final example below. In this case, since cherries is not a key, return 0 (instead of None).

+ + +inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + +print(inventory.get("apples")) +print(inventory.get("cherries")) + +print(inventory.get("cherries", 0)) + + + +

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

+ + + + + + +
+

+ Check your understanding +

+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +keylist = list(mydict.keys()) +keylist.sort() +print(keylist[3]) + + +
+ + + +

cat

+
+ + keylist is a list of all the keys which is then sorted. cat would be at index 1. + +
+ + +

dog

+
+ + keylist is a list of all the keys which is then sorted. dog would be at index 2. + +
+ + +

elephant

+
+ + Yes, the list of keys is sorted and the item at index 3 is printed. + +
+ + +

bear

+
+ + keylist is a list of all the keys which is then sorted. bear would be at index 0. + +
+
+
+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +answer = mydict.get("cat") // mydict.get("dog") +print(answer) + + +
+ + + +

2

+
+ + get returns the value associated with a given key so this divides 12 by 6. + +
+ + +

0.5

+
+ + 12 is divided by 6, not the other way around. + +
+ + +

bear

+
+ + Take another look at the example for get above. get returns the value associated with a given key. + +
+ + +

Error, divide is not a valid operation on dictionaries.

+
+ + The integer division operator is being used on the values returned from the get method, not on the dictionary. + +
+
+
+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +print("dog" in mydict) + + +
+ + + +

True

+
+ + Yes, dog is a key in the dictionary. + +
+ + +

False

+
+ + The in operator returns True if a key is in the dictionary, False otherwise. + +
+
+
+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +print(23 in mydict) + + +
+ + + +

True

+
+ + 23 is a value in the dictionary, not a key. + +
+ + +

False

+
+ + Yes, the in operator returns True if a key is in the dictionary, False otherwise. + +
+
+
+ + +

What is printed by the following statements?

+ + +total = 0 +mydict = {"cat":12, "dog":6, "elephant":23, "bear":20} +for akey in mydict: + if len(akey) > 3: + total = total + mydict[akey] +print(total) + + +
+ + + +

18

+
+ + Add the values that have keys greater than 3, not equal to 3. + +
+ + +

43

+
+ + Yes, the for statement iterates over the keys. It adds the values of the keys that have length greater than 3. + +
+ + +

0

+
+ + This is the accumulator pattern. total starts at 0 but then changes as the iteration proceeds. + +
+ + +

61

+
+ + Not all the values are added together. The if statement only chooses some of them. + +
+
+
+
diff --git a/pretext/AdditionalTopics/Dictionaryoperations.ptx b/pretext/AdditionalTopics/Dictionaryoperations.ptx new file mode 100644 index 000000000..14713886c --- /dev/null +++ b/pretext/AdditionalTopics/Dictionaryoperations.ptx @@ -0,0 +1,88 @@ + +
+ Dictionary Operations +

The del statement removes a key-value pair from a dictionary. For example, + the following dictionary contains the names of various fruits and the number of + each fruit in stock. If someone buys all of the pears, we can remove the entry from the dictionary.

+ + + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + + del inventory['pears'] + + + +

Dictionaries are also mutable. As we've seen before with lists, this means that the dictionary can + be modified by referencing an association on the left hand side of the assignment statement. In the previous + example, instead of deleting the entry for pears, we could have set the inventory to 0. +

+ + + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + + inventory['pears'] = 0 + + +

Similarily, + a new shipment of 200 bananas arriving could be handled like this.

+ + + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} + inventory['bananas'] = inventory['bananas'] + 200 + + + numItems = len(inventory) + + +

Notice that there are now 512 bananas—the dictionary has been modified. Note also that the len function also works on dictionaries. It returns the number + of key-value pairs:

+

+ Check your understanding +

+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23} +mydict["mouse"] = mydict["cat"] + mydict["dog"] +print(mydict["mouse"]) + + +
+ + + +

12

+
+ + 12 is associated with the key cat. + +
+ + +

0

+
+ + The key mouse will be associated with the sum of the two values. + +
+ + +

18

+
+ + Yes, add the value for cat and the value for dog (12 + 6) and create a new entry for mouse. + +
+ + +

Error, there is no entry with mouse as the key.

+
+ + Since the new key is introduced on the left hand side of the assignment statement, a new key-value pair is added to the dictionary. + +
+
+
+
diff --git a/pretext/AdditionalTopics/Exercises.ptx b/pretext/AdditionalTopics/Exercises.ptx new file mode 100644 index 000000000..4806889e7 --- /dev/null +++ b/pretext/AdditionalTopics/Exercises.ptx @@ -0,0 +1,532 @@ + + + Exercises + + +

Write a program that allows the user to enter a string. It then prints a + table of the letters of the alphabet in alphabetical order which occur in + the string together with the number of times each letter occurs. Case should + be ignored. A sample run of the program might look this this:

+
Please enter a sentence: ThiS is String with Upper and lower case Letters.
+a  2
+c  1
+d  1
+e  5
+g  1
+h  2
+i  4
+l  2
+n  2
+o  1
+p  2
+r  4
+s  5
+t  5
+u  1
+w  2
+$
+
+ + + + + + + + +x = input("Enter a sentence") + +x = x.lower() # convert to all lowercase + +alphabet = 'abcdefghijklmnopqrstuvwxyz' + +letter_count = {} # empty dictionary +for char in x: + if char in alphabet: # ignore any punctuation, numbers, etc + if char in letter_count: + letter_count[char] = letter_count[char] + 1 + else: + letter_count[char] = 1 + +keys = letter_count.keys() +for char in sorted(keys): + print(char, letter_count[char]) + + + +
+
+

Give the Python interpreter's response to each of the following from a + continuous interpreter session:

+

+

    +
  1. + + +>>> d = {'apples': 15, 'bananas': 35, 'grapes': 12} +>>> d['banana'] + + +
  2. +
  3. + + +>>> d['oranges'] = 20 +>>> len(d) + + +
  4. +
  5. + + +>>> 'grapes' in d + + +
  6. +
  7. + + +>>> d['pears'] + + +
  8. +
  9. + + +>>> d.get('pears', 0) + + +
  10. +
  11. + + +>>> fruits = d.keys() +>>> fruits.sort() +>>> print(fruits) + + +
  12. +
  13. + + +>>> del d['apples'] +>>> 'apples' in d + + +
  14. +
+

+
+

Be sure you understand why you get each result. Then apply what you + have learned to fill in the body of the function below, and add code for + the tests indicated:

+ + +def add_fruit(inventory, fruit, quantity=0): + pass + +# make these tests work... +new_inventory = {} +add_fruit(new_inventory, 'strawberries', 10) +# test that 'strawberries' in new_inventory +# test that new_inventory['strawberries'] is 10 +add_fruit(new_inventory, 'strawberries', 25) +# test that new_inventory['strawberries'] is now 35) + + + + +

Write a program called alice_words.py that creates a text file named + alice_words.txt containing an alphabetical listing of all the words, and the + number of times each occurs, in the text version of Alice's Adventures in Wonderland. + (You can obtain a free plain text version of the book, along with many others, from + http://www.gutenberg.org.) The first 10 lines of your output file should look + something like this

+
+ + + + + Word + + + Count + + + + + a + + + 631 + + + + + a-piece + + + 1 + + + + + abide + + + 1 + + + + + able + + + 1 + + + + + about + + + 94 + + + + + above + + + 3 + + + + + absence + + + 1 + + + + + absurd + + + 2 + + + +
+
+

How many times does the word, alice, occur in the book? If you are writing this + in the activecode window simply print out the results rather than write them to a file.

+
+ + + + + + + f = open('alice.txt', 'r') + +count = {} + +for line in f: + for word in line.split(): + + # remove punctuation + word = word.replace('_', '').replace('"', '').replace(',', '').replace('.', '') + word = word.replace('-', '').replace('?', '').replace('!', '').replace("'", "") + word = word.replace('(', '').replace(')', '').replace(':', '').replace('[', '') + word = word.replace(']', '').replace(';', '') + + # ignore case + word = word.lower() + + # ignore numbers + if word.isalpha(): + if word in count: + count[word] = count[word] + 1 + else: + count[word] = 1 + +keys = count.keys() +keys.sort() + +# save the word count analysis to a file +out = open('alice_words.txt', 'w') + +for word in keys: + out.write(word + " " + str(count[word])) + out.write('\n') + +print("The word 'alice' appears " + str(count['alice']) + " times in the book.") + + +f = open('alice.txt', 'r') + +count = {} + +for line in f: + for word in line.split(): + + # remove punctuation + word = word.replace('_', '').replace('"', '').replace(',', '').replace('.', '') + word = word.replace('-', '').replace('?', '').replace('!', '').replace("'", "") + word = word.replace('(', '').replace(')', '').replace(':', '').replace('[', '') + word = word.replace(']', '').replace(';', '') + + # ignore case + word = word.lower() + + # ignore numbers + if word.isalpha(): + if word in count: + count[word] = count[word] + 1 + else: + count[word] = 1 + +keys = count.keys() +keys.sort() + +# save the word count analysis to a file +out = open('alice_words.txt', 'w') + +for word in keys: + out.write(word + " " + str(count[word])) + out.write('\n') + +print("The word 'alice' appears " + str(count['alice']) + " times in the book.") + + +
+ + +

What is the longest word in Alice in Wonderland? How many characters does it have?

+
+ + + + + +
+ + +

Here's a table of English to Pirate translations

+ + + + + English + + + Pirate + + + + + sir + + + matey + + + + + hotel + + + fleabag inn + + + + + student + + + swabbie + + + + + boy + + + matey + + + + + madam + + + proud beauty + + + + + professor + + + foul blaggart + + + + + restaurant + + + galley + + + + + your + + + yer + + + + + excuse + + + arr + + + + + students + + + swabbies + + + + + are + + + be + + + + + lawyer + + + foul blaggart + + + + + the + + + th' + + + + + restroom + + + head + + + + + my + + + me + + + + + hello + + + avast + + + + + is + + + be + + + + + man + + + matey + + + +
+

Write a function named translator that takes a parameter containing a sentence in English + (no punctuation and all words in lowercase) and returns that sentence translated to Pirate.

+

For example, the sentence hello there students should be translated to avast there swabbies.

+
+ + +def translator(english): + + pirate = {} + pirate['sir'] = 'matey' + pirate['hotel'] = 'fleabag inn' + pirate['student'] = 'swabbie' + pirate['boy'] = 'matey' + pirate['restaurant'] = 'galley' + pirate['hello'] = 'avast' + pirate['students'] = 'swabbies' + + # Complete the function + +==== +from unittest.gui import TestCaseGui + +class myTests(TestCaseGui): + + def testOne(self): + self.assertEqual(translator("hello there students"),'avast there swabbies','translator("hello there students") yields "avast there swabbies"') + self.assertEqual(translator("the boy stayed in the hotel"),'the matey stayed in the fleabag inn','translator("the boy stayed in the hotel") yields "the matey stayed in the fleabag inn"') + +myTests().main() + + + + + +def translator(sentence): + + pirate = {} + pirate['sir'] = 'matey' + pirate['hotel'] = 'fleabag inn' + pirate['student'] = 'swabbie' + pirate['boy'] = 'matey' + pirate['restaurant'] = 'galley' + pirate['hello'] = 'avast' + pirate['students'] = 'swabbies' + + psentence = [] + words = sentence.split() + for aword in words: + if aword in pirate: + psentence.append(pirate[aword]) + else: + psentence.append(aword) + + return " ".join(psentence) + + + +
+
diff --git a/pretext/AdditionalTopics/Glossary.ptx b/pretext/AdditionalTopics/Glossary.ptx new file mode 100644 index 000000000..e6a39e402 --- /dev/null +++ b/pretext/AdditionalTopics/Glossary.ptx @@ -0,0 +1,33 @@ + +
+ Glossary + + + comprehension +

A specific Python construction that allows collection types to be created and filled with a single line of code.

+
+ + dictionary +

A collection of key-value pairs that maps from keys to values. The keys + can be any immutable type, and the values can be any type.

+
+ + key +

A data item that is mapped to a value in a dictionary. Keys are used + to look up values in a dictionary.

+
+ + key-value pair +

One of the pairs of items in a dictionary. Values are looked up in a + dictionary by key.

+
+ + mapping type +

A mapping type is a data type comprised of a collection of keys and + associated values. Python's only built-in mapping type is the + dictionary. Dictionaries implement the + associative array + abstract data type.

+
+
+
diff --git a/pretext/AdditionalTopics/ListComprehensions.ptx b/pretext/AdditionalTopics/ListComprehensions.ptx index 601376f29..b5a4eaf74 100644 --- a/pretext/AdditionalTopics/ListComprehensions.ptx +++ b/pretext/AdditionalTopics/ListComprehensions.ptx @@ -1,8 +1,14 @@
List Comprehensions -

The previous example creates a list from a sequence of values based on some selection criteria. An easy way to do this type of processing in Python is to use a list comprehension. List comprehensions are concise ways to create lists. The general syntax is:

-
[<expression> for <item> in <sequence> if  <condition>]
+

Generating or modifying a list of values based on some consistent rule is a very common operation done in Python. Take, for example, + generating a list of values according to a math function, or performing the same string operation on a list of words. This is common + enough that Python has built-in syntax to construct these smaller, collection-producing loops succinctly. These are known as comprehensions, + and can be done with several different collection types.

+ +

A comprehension that generates a list is, naturally, known as a list comprehension. + List comprehensions are concise ways to create lists. The general syntax is:

+
[<expression> for <item> in <sequence> if <condition>]

where the if clause is optional. For example,

@@ -14,7 +20,7 @@ print(yourlist)

The expression describes each element of the list that is being built. The for clause iterates through each item in a sequence. The items are filtered by the if clause if there is one. In the example above, the for statement lets item take on all the values in the list mylist. Each item is then squared before it is added to the list that is being built. The result is a list of squares of the values in mylist.

-

To write the primes_upto function we will use the is_prime function to filter the sequence of integers coming from the range function. In other words, for every integer from 2 up to but not including n, if the integer is prime, keep it in the list.

+

To write a primes_upto function we can use the previously-made is_prime function to filter the sequence of integers coming from a range function. In other words, for every integer from 2 up to but not including n, if the integer is prime, keep it in the list.

def primes_upto(n): diff --git a/pretext/AdditionalTopics/intro-Dictionaries.ptx b/pretext/AdditionalTopics/intro-Dictionaries.ptx new file mode 100644 index 000000000..f7db54598 --- /dev/null +++ b/pretext/AdditionalTopics/intro-Dictionaries.ptx @@ -0,0 +1,139 @@ + +
+ Dictionaries +

All of the compound data types we have studied in detail so far — strings, + lists, and tuples — are sequential collections. This means that the items in the collection are + ordered from left to right and they use integers as indices to access + the values they contain.

+

+ Dictionaries are a different kind of collection. They are Python's + built-in mapping type. A map is an unordered, associative collection. The association, or mapping, + is from a key, which can be any immutable type, + to a value, which can be any Python data object.

+

As an example, we will create a dictionary to translate English words into + Spanish. For this dictionary, the keys are strings and the values will also be strings.

+

One way to create a dictionary is to start with the empty dictionary and add + key-value pairs. The empty dictionary is denoted {} +

+ + + eng2sp = {} + eng2sp['one'] = 'uno' + eng2sp['two'] = 'dos' + eng2sp['three'] = 'tres' + + +

The first assignment creates an empty dictionary named eng2sp. The other + assignments add new key-value pairs to the dictionary. The left hand side gives the dictionary and the key being associated. The right hand side gives the value being associated with that key. + We can print the current + value of the dictionary in the usual way. + The key-value pairs of the dictionary are separated by commas. Each pair + contains a key and a value separated by a colon.

+

The order of the pairs may not be what you expected. Python uses complex + algorithms, designed for very fast access, to determine where the + key-value pairs are stored in a dictionary. + For our purposes we can think of this ordering as unpredictable.

+

Another way to create a dictionary is to provide a list of key-value pairs + using the same syntax as the previous output.

+ + + eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} + print(eng2sp) + + + +

It doesn't matter what order we write the pairs. The values in a dictionary are + accessed with keys, not with indices, so there is no need to care about + ordering.

+

Here is how we use a key to look up the corresponding value.

+ + +eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} + +value = eng2sp['two'] +print(value) + + +

The key 'two' yields the value 'dos'. +

+ +

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

+ + + + + + +
+

+ Check your understanding +

+ + +

A dictionary is an unordered collection of key-value pairs.

+
+ + + +

False

+
+ + Dictionaries associate keys with values but there is no assumed order for the entries. + +
+ + +

True

+
+ + Yes, dictionaries are associative collections meaning that they store key-value pairs. + +
+
+
+ + +

What is printed by the following statements?

+ + +mydict = {"cat":12, "dog":6, "elephant":23} +print(mydict["dog"]) + + +
+ + + +

12

+
+ + 12 is associated with the key cat. + +
+ + +

6

+
+ + Yes, 6 is associated with the key dog. + +
+ + +

23

+
+ + 23 is associated with the key elephant. + +
+ + +

Error, you cannot use the index operator with a dictionary.

+
+ + The [ ] operator, when used with a dictionary, will look up a value based on its key. + +
+
+
+
diff --git a/pretext/AdditionalTopics/toctree.ptx b/pretext/AdditionalTopics/toctree.ptx index ad7c68063..8e1f25bd6 100644 --- a/pretext/AdditionalTopics/toctree.ptx +++ b/pretext/AdditionalTopics/toctree.ptx @@ -2,4 +2,10 @@ 4Additional Topics 4 +4 +4 +4 +4 +4 +4 From a47f06c91edda2d1d7ca7885c701d29da0b6c30d Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 13 Jul 2023 13:29:23 -0600 Subject: [PATCH 62/90] Removed CSV CSV subchapters removed to be replaced with a JuPyter notebook reading instead. --- pretext/Files/toctree.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Files/toctree.ptx b/pretext/Files/toctree.ptx index afa1b9357..f52d9ed00 100644 --- a/pretext/Files/toctree.ptx +++ b/pretext/Files/toctree.ptx @@ -8,7 +8,7 @@ 4 4 4 -4 -4 + 4 From ca8a834e1dc05595018eb256ef29a23271104516 Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 13 Jul 2023 14:11:15 -0600 Subject: [PATCH 63/90] Video Lectures Added Added sections that embed Ethan's video lectures. The weeks without a corresponding reading: 9 and 11, are not embedded. --- pretext/ClassesDiggingDeeper/toctree.ptx | 1 + pretext/ClassesDiggingDeeper/video-classes.ptx | 7 +++++++ pretext/ComplexLogic/toctree.ptx | 1 + pretext/ComplexLogic/video-complex.ptx | 7 +++++++ pretext/Files/toctree.ptx | 1 + pretext/Files/video-files.ptx | 7 +++++++ pretext/IntroRecursion/toctree.ptx | 1 + pretext/IntroRecursion/video-recursion.ptx | 7 +++++++ pretext/Iteration/toctree.ptx | 2 ++ pretext/Iteration/video-for.ptx | 7 +++++++ pretext/Iteration/video-while.ptx | 7 +++++++ pretext/Lists/toctree.ptx | 1 + pretext/Lists/video-lists.ptx | 8 ++++++++ pretext/PythonModules/toctree.ptx | 1 + pretext/PythonModules/video-functions.ptx | 7 +++++++ pretext/Selection/toctree.ptx | 2 ++ pretext/Selection/video-branching.ptx | 7 +++++++ pretext/Selection/video-logic.ptx | 7 +++++++ pretext/SimplePythonData/toctree.ptx | 1 + pretext/SimplePythonData/video-simpledata.ptx | 8 ++++++++ 20 files changed, 90 insertions(+) create mode 100644 pretext/ClassesDiggingDeeper/video-classes.ptx create mode 100644 pretext/ComplexLogic/video-complex.ptx create mode 100644 pretext/Files/video-files.ptx create mode 100644 pretext/IntroRecursion/video-recursion.ptx create mode 100644 pretext/Iteration/video-for.ptx create mode 100644 pretext/Iteration/video-while.ptx create mode 100644 pretext/Lists/video-lists.ptx create mode 100644 pretext/PythonModules/video-functions.ptx create mode 100644 pretext/Selection/video-branching.ptx create mode 100644 pretext/Selection/video-logic.ptx create mode 100644 pretext/SimplePythonData/video-simpledata.ptx diff --git a/pretext/ClassesDiggingDeeper/toctree.ptx b/pretext/ClassesDiggingDeeper/toctree.ptx index 32970d8df..e268cd4dc 100644 --- a/pretext/ClassesDiggingDeeper/toctree.ptx +++ b/pretext/ClassesDiggingDeeper/toctree.ptx @@ -6,4 +6,5 @@ 4 4 4 +4 diff --git a/pretext/ClassesDiggingDeeper/video-classes.ptx b/pretext/ClassesDiggingDeeper/video-classes.ptx new file mode 100644 index 000000000..5ff821db7 --- /dev/null +++ b/pretext/ClassesDiggingDeeper/video-classes.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 13 Video Lecture:

+
diff --git a/pretext/ComplexLogic/toctree.ptx b/pretext/ComplexLogic/toctree.ptx index 0a254a223..480ba232e 100644 --- a/pretext/ComplexLogic/toctree.ptx +++ b/pretext/ComplexLogic/toctree.ptx @@ -12,4 +12,5 @@ 4 4 4 +4 diff --git a/pretext/ComplexLogic/video-complex.ptx b/pretext/ComplexLogic/video-complex.ptx new file mode 100644 index 000000000..8f7367409 --- /dev/null +++ b/pretext/ComplexLogic/video-complex.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 8 Video Lecture:

+
diff --git a/pretext/Files/toctree.ptx b/pretext/Files/toctree.ptx index f52d9ed00..c701cec7e 100644 --- a/pretext/Files/toctree.ptx +++ b/pretext/Files/toctree.ptx @@ -11,4 +11,5 @@ 4 +4 diff --git a/pretext/Files/video-files.ptx b/pretext/Files/video-files.ptx new file mode 100644 index 000000000..5da75b1d7 --- /dev/null +++ b/pretext/Files/video-files.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 10 Video Lecture:

+
diff --git a/pretext/IntroRecursion/toctree.ptx b/pretext/IntroRecursion/toctree.ptx index 5b67d043d..8f5be90eb 100644 --- a/pretext/IntroRecursion/toctree.ptx +++ b/pretext/IntroRecursion/toctree.ptx @@ -7,4 +7,5 @@ 4 4 4 +4 diff --git a/pretext/IntroRecursion/video-recursion.ptx b/pretext/IntroRecursion/video-recursion.ptx new file mode 100644 index 000000000..945e9d30d --- /dev/null +++ b/pretext/IntroRecursion/video-recursion.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 12 Video Lecture:

+
diff --git a/pretext/Iteration/toctree.ptx b/pretext/Iteration/toctree.ptx index 65b198c9f..9dfb0586a 100644 --- a/pretext/Iteration/toctree.ptx +++ b/pretext/Iteration/toctree.ptx @@ -8,10 +8,12 @@ 4 4 4 +4 4 4 4 4 4 4 +4 diff --git a/pretext/Iteration/video-for.ptx b/pretext/Iteration/video-for.ptx new file mode 100644 index 000000000..531b2174f --- /dev/null +++ b/pretext/Iteration/video-for.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 6 Video Lecture:

+
diff --git a/pretext/Iteration/video-while.ptx b/pretext/Iteration/video-while.ptx new file mode 100644 index 000000000..5456b8a93 --- /dev/null +++ b/pretext/Iteration/video-while.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 5 Video Lecture:

+
diff --git a/pretext/Lists/toctree.ptx b/pretext/Lists/toctree.ptx index 0c98ce72d..96b9c0a70 100644 --- a/pretext/Lists/toctree.ptx +++ b/pretext/Lists/toctree.ptx @@ -15,4 +15,5 @@ 4 4 4 +4 diff --git a/pretext/Lists/video-lists.ptx b/pretext/Lists/video-lists.ptx new file mode 100644 index 000000000..10f6ffdaf --- /dev/null +++ b/pretext/Lists/video-lists.ptx @@ -0,0 +1,8 @@ + +
+ Practice Video Lecture +

Our course mentor Ethan has generously put together short video lectures to culminate each weekly reading. Now that you have finished chapters 3 and 4, the video is embedded below. + It is not required, but you may find it helpful if the reading left you with questions.

+
diff --git a/pretext/PythonModules/toctree.ptx b/pretext/PythonModules/toctree.ptx index ae3a42904..77275913f 100644 --- a/pretext/PythonModules/toctree.ptx +++ b/pretext/PythonModules/toctree.ptx @@ -6,4 +6,5 @@ 4 4 4 +4 diff --git a/pretext/PythonModules/video-functions.ptx b/pretext/PythonModules/video-functions.ptx new file mode 100644 index 000000000..0d1eaa5ed --- /dev/null +++ b/pretext/PythonModules/video-functions.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 7 Video Lecture:

+
diff --git a/pretext/Selection/toctree.ptx b/pretext/Selection/toctree.ptx index 380b0ade8..5a7ff7e66 100644 --- a/pretext/Selection/toctree.ptx +++ b/pretext/Selection/toctree.ptx @@ -9,7 +9,9 @@ 4 4 4 +4 4 4 4 +4 diff --git a/pretext/Selection/video-branching.ptx b/pretext/Selection/video-branching.ptx new file mode 100644 index 000000000..2aef60b72 --- /dev/null +++ b/pretext/Selection/video-branching.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 3 Video Lecture:

+
diff --git a/pretext/Selection/video-logic.ptx b/pretext/Selection/video-logic.ptx new file mode 100644 index 000000000..a45f7a690 --- /dev/null +++ b/pretext/Selection/video-logic.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 4 Video Lecture:

+
diff --git a/pretext/SimplePythonData/toctree.ptx b/pretext/SimplePythonData/toctree.ptx index 7eb94a591..f2ac61a99 100644 --- a/pretext/SimplePythonData/toctree.ptx +++ b/pretext/SimplePythonData/toctree.ptx @@ -13,4 +13,5 @@ 4 4 4 +4 diff --git a/pretext/SimplePythonData/video-simpledata.ptx b/pretext/SimplePythonData/video-simpledata.ptx new file mode 100644 index 000000000..f2f1fb92b --- /dev/null +++ b/pretext/SimplePythonData/video-simpledata.ptx @@ -0,0 +1,8 @@ + +
+ Practice Video Lecture +

Our course mentor Ethan has generously put together short video lectures to culminate each weekly reading. Now that you have finished chapters 1 and 2, the video is embedded below. + It is not required, but you may find it helpful if the reading left you with questions.

+
From 749d7a1908e35acb90a652aee20c2b847930fdc1 Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 13 Jul 2023 14:14:00 -0600 Subject: [PATCH 64/90] Removed codelens with input Codelens doesn't seem able to accept user input, so one activity that used it was removed. --- pretext/Iteration/ThewhileStatement.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Iteration/ThewhileStatement.ptx b/pretext/Iteration/ThewhileStatement.ptx index 4a1eca840..fc9d1eb6b 100644 --- a/pretext/Iteration/ThewhileStatement.ptx +++ b/pretext/Iteration/ThewhileStatement.ptx @@ -88,7 +88,7 @@ while aNumber is less than or equal to aBound, continue executing the body of the loop. Within the body, each time, update theSum using the accumulator pattern and increment aNumber. After the body of the loop, we go back up to the condition of the while and reevaluate it. When aNumber becomes greater than aBound, the condition fails and flow of control continues to the return statement.

-

The same program in codelens will allow you to observe the flow of execution.

+

In the case shown above, we can prove that the loop terminates because we know that the value of aBound is finite, and we can see that the value of aNumber From f38fdcd084c5aab2ebaacc8567627f651d0635be Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 13 Jul 2023 14:23:44 -0600 Subject: [PATCH 65/90] Buggy Content Fixes Removed/disabled two areas that weren't working in production --- pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx | 4 ++-- pretext/IntroRecursion/toctree.ptx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx index b96ff174c..f4dd36055 100644 --- a/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx +++ b/pretext/ComplexLogic/TheAccumulatorPatternwithLists.ptx @@ -264,7 +264,7 @@ print(min_value) - +

diff --git a/pretext/IntroRecursion/toctree.ptx b/pretext/IntroRecursion/toctree.ptx index 8f5be90eb..482fcc5a9 100644 --- a/pretext/IntroRecursion/toctree.ptx +++ b/pretext/IntroRecursion/toctree.ptx @@ -6,6 +6,6 @@ 4 4 4 -4 + 4 From 7a31cfb0b51996e47c20ee9b337160d1d322698c Mon Sep 17 00:00:00 2001 From: robotuw Date: Sun, 6 Aug 2023 14:13:11 -0600 Subject: [PATCH 66/90] Update fStrings.ptx Removed text that was outdated. --- pretext/Strings/fStrings.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Strings/fStrings.ptx b/pretext/Strings/fStrings.ptx index c610b06d5..8094f9e3e 100644 --- a/pretext/Strings/fStrings.ptx +++ b/pretext/Strings/fStrings.ptx @@ -81,8 +81,8 @@ print(calculation) b = 9 setStr = f'The set is {​{ {a},{b} }​}.' print(setStr) -

Unfortunately, at the time of this writing, the ActiveCode format implementation has a bug, - printing doubled braces, but standard Python prints {5, 9}.

+

What is printed by the following statements?

From 7c058722d935d6d9867f87bff0525a0612e6b56e Mon Sep 17 00:00:00 2001 From: robotuw Date: Thu, 10 Aug 2023 13:30:28 -0600 Subject: [PATCH 67/90] Update intro-VariablesExpressionsandStatements.ptx Removed an old embedded video that didn't get caught --- .../intro-VariablesExpressionsandStatements.ptx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretext/SimplePythonData/intro-VariablesExpressionsandStatements.ptx b/pretext/SimplePythonData/intro-VariablesExpressionsandStatements.ptx index 9c6ce3ebb..7f24600d7 100644 --- a/pretext/SimplePythonData/intro-VariablesExpressionsandStatements.ptx +++ b/pretext/SimplePythonData/intro-VariablesExpressionsandStatements.ptx @@ -1,7 +1,7 @@
Variables, Expressions and Statements -
From 76878293dbc06119e602517dafeb2d1123bf073a Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:43:02 -0600 Subject: [PATCH 70/90] Update all videos and add week 15 video --- pretext/AdditionalTopics/toctree.ptx | 1 + pretext/AdditionalTopics/video-more-python.ptx | 7 +++++++ pretext/ClassesDiggingDeeper/video-classes.ptx | 2 +- pretext/ComplexLogic/video-complex.ptx | 2 +- pretext/Files/video-files.ptx | 2 +- pretext/IntroRecursion/video-recursion.ptx | 2 +- pretext/Iteration/video-for.ptx | 2 +- pretext/Iteration/video-while.ptx | 2 +- pretext/Lists/video-lists.ptx | 2 +- pretext/PythonModules/video-functions.ptx | 2 +- pretext/Selection/video-branching.ptx | 2 +- pretext/Selection/video-logic.ptx | 2 +- 12 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 pretext/AdditionalTopics/video-more-python.ptx diff --git a/pretext/AdditionalTopics/toctree.ptx b/pretext/AdditionalTopics/toctree.ptx index 8e1f25bd6..512f7bfd5 100644 --- a/pretext/AdditionalTopics/toctree.ptx +++ b/pretext/AdditionalTopics/toctree.ptx @@ -8,4 +8,5 @@ 4 4 4 +4 diff --git a/pretext/AdditionalTopics/video-more-python.ptx b/pretext/AdditionalTopics/video-more-python.ptx new file mode 100644 index 000000000..485b0ef9f --- /dev/null +++ b/pretext/AdditionalTopics/video-more-python.ptx @@ -0,0 +1,7 @@ + +
+ Practice Video Lecture +

Week 15 Video Lecture:

+
diff --git a/pretext/ClassesDiggingDeeper/video-classes.ptx b/pretext/ClassesDiggingDeeper/video-classes.ptx index 5ff821db7..8693bbc58 100644 --- a/pretext/ClassesDiggingDeeper/video-classes.ptx +++ b/pretext/ClassesDiggingDeeper/video-classes.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 13 Video Lecture:

-
diff --git a/pretext/ComplexLogic/video-complex.ptx b/pretext/ComplexLogic/video-complex.ptx index 8f7367409..6d785a21b 100644 --- a/pretext/ComplexLogic/video-complex.ptx +++ b/pretext/ComplexLogic/video-complex.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 8 Video Lecture:

-
diff --git a/pretext/Files/video-files.ptx b/pretext/Files/video-files.ptx index 5da75b1d7..57c4a08a0 100644 --- a/pretext/Files/video-files.ptx +++ b/pretext/Files/video-files.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 10 Video Lecture:

-
diff --git a/pretext/IntroRecursion/video-recursion.ptx b/pretext/IntroRecursion/video-recursion.ptx index 945e9d30d..1872c4579 100644 --- a/pretext/IntroRecursion/video-recursion.ptx +++ b/pretext/IntroRecursion/video-recursion.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 12 Video Lecture:

-
diff --git a/pretext/Iteration/video-for.ptx b/pretext/Iteration/video-for.ptx index 531b2174f..75a35c372 100644 --- a/pretext/Iteration/video-for.ptx +++ b/pretext/Iteration/video-for.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 6 Video Lecture:

-
diff --git a/pretext/Iteration/video-while.ptx b/pretext/Iteration/video-while.ptx index 5456b8a93..83b92278d 100644 --- a/pretext/Iteration/video-while.ptx +++ b/pretext/Iteration/video-while.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 5 Video Lecture:

-
diff --git a/pretext/Lists/video-lists.ptx b/pretext/Lists/video-lists.ptx index 10f6ffdaf..4e5e9eb8d 100644 --- a/pretext/Lists/video-lists.ptx +++ b/pretext/Lists/video-lists.ptx @@ -3,6 +3,6 @@ Practice Video Lecture

Our course mentor Ethan has generously put together short video lectures to culminate each weekly reading. Now that you have finished chapters 3 and 4, the video is embedded below. It is not required, but you may find it helpful if the reading left you with questions.

-
diff --git a/pretext/PythonModules/video-functions.ptx b/pretext/PythonModules/video-functions.ptx index 0d1eaa5ed..0df11c907 100644 --- a/pretext/PythonModules/video-functions.ptx +++ b/pretext/PythonModules/video-functions.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 7 Video Lecture:

-
diff --git a/pretext/Selection/video-branching.ptx b/pretext/Selection/video-branching.ptx index 2aef60b72..e54f4cc78 100644 --- a/pretext/Selection/video-branching.ptx +++ b/pretext/Selection/video-branching.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 3 Video Lecture:

-
diff --git a/pretext/Selection/video-logic.ptx b/pretext/Selection/video-logic.ptx index a45f7a690..f82b5f8c5 100644 --- a/pretext/Selection/video-logic.ptx +++ b/pretext/Selection/video-logic.ptx @@ -2,6 +2,6 @@
Practice Video Lecture

Week 4 Video Lecture:

-
From d8a93f098789557e49322991c2c734eb2d31025d Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:16:45 -0700 Subject: [PATCH 71/90] Bug fixes (#2) * convert codelens to activecode * Remove runestone stuff from ch1 glossary --- pretext/AdditionalTopics/Dictionaryoperations.ptx | 6 +++--- pretext/AdditionalTopics/intro-Dictionaries.ptx | 14 +++++++------- pretext/ClassesBasics/ImprovingourConstructor.ptx | 2 +- pretext/ClassesBasics/UserDefinedClasses.ptx | 2 +- pretext/ComplexLogic/Aliasing.ptx | 2 +- pretext/ComplexLogic/ObjectsandReferences.ptx | 2 +- pretext/ComplexLogic/PureFunctions.ptx | 2 +- pretext/ComplexLogic/RepetitionandReferences.ptx | 2 +- .../TheAccumulatorPatternwithStrings.ptx | 2 +- pretext/ComplexLogic/UsingListsasParameters.ptx | 2 +- pretext/Dictionaries/Dictionaryoperations.ptx | 6 +++--- pretext/Dictionaries/intro-Dictionaries.ptx | 6 +++--- pretext/Functions/BooleanFunctions.ptx | 2 +- .../Functions/Functionscancallotherfunctions.ptx | 2 +- pretext/Functions/Functionsthatreturnvalues.ptx | 4 ++-- pretext/Functions/TheAccumulatorPattern.ptx | 2 +- .../Functions/Variablesandparametersarelocal.ptx | 6 +++--- pretext/GeneralIntro/Glossary.ptx | 8 -------- .../SpecialWaystoExecutePythoninthisBook.ptx | 2 +- .../2DimensionalIterationImageProcessing.ptx | 2 +- .../Iteration/FlowofExecutionofthewhileLoop.ptx | 2 +- pretext/Iteration/NewtonsMethod.ptx | 2 +- pretext/Iteration/TherangeFunction.ptx | 4 ++-- pretext/Iteration/ThewhileStatement.ptx | 2 +- pretext/Iteration/TraversalandthewhileLoop.ptx | 2 +- pretext/Lists/AppendversusConcatenate.ptx | 6 +++--- pretext/Lists/CloningLists.ptx | 2 +- pretext/Lists/ConcatenationandRepetition.ptx | 2 +- pretext/Lists/ListsareMutable.ptx | 2 +- .../PythonTurtle/FlowofExecutionoftheforLoop.ptx | 2 +- pretext/Selection/Nestedconditionals.ptx | 2 +- pretext/SimplePythonData/OperatorsandOperands.ptx | 2 +- pretext/SimplePythonData/Variables.ptx | 4 ++-- 33 files changed, 51 insertions(+), 59 deletions(-) diff --git a/pretext/AdditionalTopics/Dictionaryoperations.ptx b/pretext/AdditionalTopics/Dictionaryoperations.ptx index 14713886c..c0c5ca2db 100644 --- a/pretext/AdditionalTopics/Dictionaryoperations.ptx +++ b/pretext/AdditionalTopics/Dictionaryoperations.ptx @@ -4,7 +4,7 @@

The del statement removes a key-value pair from a dictionary. For example, the following dictionary contains the names of various fruits and the number of each fruit in stock. If someone buys all of the pears, we can remove the entry from the dictionary.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} @@ -16,7 +16,7 @@ be modified by referencing an association on the left hand side of the assignment statement. In the previous example, instead of deleting the entry for pears, we could have set the inventory to 0.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} @@ -25,7 +25,7 @@

Similarily, a new shipment of 200 bananas arriving could be handled like this.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} inventory['bananas'] = inventory['bananas'] + 200 diff --git a/pretext/AdditionalTopics/intro-Dictionaries.ptx b/pretext/AdditionalTopics/intro-Dictionaries.ptx index f7db54598..03a7c5e68 100644 --- a/pretext/AdditionalTopics/intro-Dictionaries.ptx +++ b/pretext/AdditionalTopics/intro-Dictionaries.ptx @@ -15,12 +15,12 @@

One way to create a dictionary is to start with the empty dictionary and add key-value pairs. The empty dictionary is denoted {}

- + - eng2sp = {} - eng2sp['one'] = 'uno' - eng2sp['two'] = 'dos' - eng2sp['three'] = 'tres' +eng2sp = {} +eng2sp['one'] = 'uno' +eng2sp['two'] = 'dos' +eng2sp['three'] = 'tres'

The first assignment creates an empty dictionary named eng2sp. The other @@ -35,7 +35,7 @@ For our purposes we can think of this ordering as unpredictable.

Another way to create a dictionary is to provide a list of key-value pairs using the same syntax as the previous output.

- + eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} print(eng2sp) @@ -46,7 +46,7 @@ accessed with keys, not with indices, so there is no need to care about ordering.

Here is how we use a key to look up the corresponding value.

- + eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} diff --git a/pretext/ClassesBasics/ImprovingourConstructor.ptx b/pretext/ClassesBasics/ImprovingourConstructor.ptx index 977f74f60..a85f45fb7 100644 --- a/pretext/ClassesBasics/ImprovingourConstructor.ptx +++ b/pretext/ClassesBasics/ImprovingourConstructor.ptx @@ -5,7 +5,7 @@ provide some additional capability for the user to pass information to the constructor. Since constructors are simply specially named functions, we can use parameters (as we've seen before) to provide the specific information.

We can make our class constructor more general by putting extra parameters into the __init__ method, as shown in this codelens example.

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ diff --git a/pretext/ClassesBasics/UserDefinedClasses.ptx b/pretext/ClassesBasics/UserDefinedClasses.ptx index 757165bb2..37bb40c2a 100644 --- a/pretext/ClassesBasics/UserDefinedClasses.ptx +++ b/pretext/ClassesBasics/UserDefinedClasses.ptx @@ -77,7 +77,7 @@ print("Nothing seems to have happened with the points") having an x and y coordinate with value 0. However, because we have not asked the point to do anything, we don't see any other result.

Simple object has state and methods

You can see this for yourself, via codelens:

- + class Point: """ Point class for representing and manipulating x,y coordinates. """ diff --git a/pretext/ComplexLogic/Aliasing.ptx b/pretext/ComplexLogic/Aliasing.ptx index 415797a7e..e450d82b0 100644 --- a/pretext/ComplexLogic/Aliasing.ptx +++ b/pretext/ComplexLogic/Aliasing.ptx @@ -16,7 +16,7 @@ print(a is b) is aliased. Changes made with one alias affect the other. In the codelens example below, you can see that a and b refer to the same list after executing the assignment statement b = a.

- + a = [81, 82, 83] b = [81, 82, 83] diff --git a/pretext/ComplexLogic/ObjectsandReferences.ptx b/pretext/ComplexLogic/ObjectsandReferences.ptx index d055a62f9..8582f42f1 100644 --- a/pretext/ComplexLogic/ObjectsandReferences.ptx +++ b/pretext/ComplexLogic/ObjectsandReferences.ptx @@ -48,7 +48,7 @@ print(a == b) a and b have the same value but do not refer to the same object.

There is one other important thing to notice about this reference diagram. The variable a is a reference to a collection of references. Those references actually refer to the integer values in the list. In other words, a list is a collection of references to objects. Interestingly, even though a and b are two different lists (two different collections of references), the integer object 81 is shared by both. Like strings, integers are also immutable so Python optimizes and lets everyone share the same object for some commonly used small integers.

Here is the example in codelens. Pay particular attention to the id values.

- + a = [81, 82, 83] b = [81, 82, 83] diff --git a/pretext/ComplexLogic/PureFunctions.ptx b/pretext/ComplexLogic/PureFunctions.ptx index f116f181a..05c7c04c0 100644 --- a/pretext/ComplexLogic/PureFunctions.ptx +++ b/pretext/ComplexLogic/PureFunctions.ptx @@ -24,7 +24,7 @@ print(things)

Once again, codelens helps us to see the actual references and objects as they are passed and returned.

- + def doubleStuff(a_list): """ Return a new list in which contains doubles of the elements in a_list. """ diff --git a/pretext/ComplexLogic/RepetitionandReferences.ptx b/pretext/ComplexLogic/RepetitionandReferences.ptx index 7e5bdaf90..b99bba568 100644 --- a/pretext/ComplexLogic/RepetitionandReferences.ptx +++ b/pretext/ComplexLogic/RepetitionandReferences.ptx @@ -44,7 +44,7 @@ print(newlist) Same reference

Here is the same example in codelens. Step through the code paying particular attention to the result of executing the assignment statement origlist[1] = 99.

- + origlist = [45, 76, 34, 55] diff --git a/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx b/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx index 5ada2d706..9212b4778 100644 --- a/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx +++ b/pretext/ComplexLogic/TheAccumulatorPatternwithStrings.ptx @@ -36,7 +36,7 @@ if eachChar != 'a' and eachChar != 'e' and eachChar != 'i' and

Take a close look also at the initialization of sWithoutVowels. We start with an empty string and then begin adding new characters to the end.

Step through the function using codelens to see the accumulator variable grow.

- + def removeVowels(s): vowels = "aeiouAEIOU" diff --git a/pretext/ComplexLogic/UsingListsasParameters.ptx b/pretext/ComplexLogic/UsingListsasParameters.ptx index 4a7a2b9d1..52b7b5853 100644 --- a/pretext/ComplexLogic/UsingListsasParameters.ptx +++ b/pretext/ComplexLogic/UsingListsasParameters.ptx @@ -29,7 +29,7 @@ print(things) If a function modifies the elements of a list parameter, the caller sees the change since the change is occurring to the original.

This can be easily seen in codelens. Note that after the call to doubleStuff, the formal parameter aList refers to the same object as the actual parameter things. There is only one copy of the list object itself.

- + def doubleStuff(aList): """ Overwrite each element in aList with double its value. """ diff --git a/pretext/Dictionaries/Dictionaryoperations.ptx b/pretext/Dictionaries/Dictionaryoperations.ptx index fd1e32bc5..3d5629d27 100644 --- a/pretext/Dictionaries/Dictionaryoperations.ptx +++ b/pretext/Dictionaries/Dictionaryoperations.ptx @@ -4,7 +4,7 @@

The del statement removes a key-value pair from a dictionary. For example, the following dictionary contains the names of various fruits and the number of each fruit in stock. If someone buys all of the pears, we can remove the entry from the dictionary.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} @@ -16,7 +16,7 @@ be modified by referencing an association on the left hand side of the assignment statement. In the previous example, instead of deleting the entry for pears, we could have set the inventory to 0.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} @@ -25,7 +25,7 @@

Similarily, a new shipment of 200 bananas arriving could be handled like this.

- + inventory = {'apples': 430, 'bananas': 312, 'oranges': 525, 'pears': 217} inventory['bananas'] = inventory['bananas'] + 200 diff --git a/pretext/Dictionaries/intro-Dictionaries.ptx b/pretext/Dictionaries/intro-Dictionaries.ptx index 5caac95fc..58eced4aa 100644 --- a/pretext/Dictionaries/intro-Dictionaries.ptx +++ b/pretext/Dictionaries/intro-Dictionaries.ptx @@ -15,7 +15,7 @@

One way to create a dictionary is to start with the empty dictionary and add key-value pairs. The empty dictionary is denoted {}

- + eng2sp = {} eng2sp['one'] = 'uno' @@ -35,7 +35,7 @@ For our purposes we can think of this ordering as unpredictable.

Another way to create a dictionary is to provide a list of key-value pairs using the same syntax as the previous output.

- + eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} print(eng2sp) @@ -46,7 +46,7 @@ accessed with keys, not with indices, so there is no need to care about ordering.

Here is how we use a key to look up the corresponding value.

- + eng2sp = {'three': 'tres', 'one': 'uno', 'two': 'dos'} diff --git a/pretext/Functions/BooleanFunctions.ptx b/pretext/Functions/BooleanFunctions.ptx index cabb804c3..49e41bacf 100644 --- a/pretext/Functions/BooleanFunctions.ptx +++ b/pretext/Functions/BooleanFunctions.ptx @@ -61,7 +61,7 @@ else:

Here is the same program in codelens. When we evaluate the if statement in the main part of the program, the evaluation of the boolean expression causes a call to the isDivisible function. This is very easy to see in codelens.

- + def isDivisible(x, y): return x % y == 0 diff --git a/pretext/Functions/Functionscancallotherfunctions.ptx b/pretext/Functions/Functionscancallotherfunctions.ptx index c98720523..d8d067edc 100644 --- a/pretext/Functions/Functionscancallotherfunctions.ptx +++ b/pretext/Functions/Functionscancallotherfunctions.ptx @@ -11,7 +11,7 @@ first function called square simply computes the square of a given number. The second function called sum_of_squares makes use of square to compute the sum of three numbers that have been squared.

- + def square(x): y = x * x diff --git a/pretext/Functions/Functionsthatreturnvalues.ptx b/pretext/Functions/Functionsthatreturnvalues.ptx index f5812b9f8..7f120fcf4 100644 --- a/pretext/Functions/Functionsthatreturnvalues.ptx +++ b/pretext/Functions/Functionsthatreturnvalues.ptx @@ -93,7 +93,7 @@ print("The result of", toSquare, "squared is", result) we will see later where it makes sense to have a return statement even when other statements follow, and the further statements are not executed.

- + def square(x): y = x * x @@ -130,7 +130,7 @@ print("The result of", toSquare, "squared is", squareResult) programmers. As you step through this example, pay very close attention to the return value in the local variables listing. Then look at what is printed when the function returns.

- + def square(x): y = x * x diff --git a/pretext/Functions/TheAccumulatorPattern.ptx b/pretext/Functions/TheAccumulatorPattern.ptx index 024174902..7200d30ea 100644 --- a/pretext/Functions/TheAccumulatorPattern.ptx +++ b/pretext/Functions/TheAccumulatorPattern.ptx @@ -47,7 +47,7 @@ print("The result of", toSquare, "squared is", squareResult) the for statement? Not sure? Try it and find out.

Here is the same program in codelens. Step through the function and watch the running total accumulate the result.

- + def square(x): runningtotal = 0 diff --git a/pretext/Functions/Variablesandparametersarelocal.ptx b/pretext/Functions/Variablesandparametersarelocal.ptx index f0c8e2a0c..e611bb3ce 100644 --- a/pretext/Functions/Variablesandparametersarelocal.ptx +++ b/pretext/Functions/Variablesandparametersarelocal.ptx @@ -5,7 +5,7 @@ variable on the left hand side of the assignment operator. It is called local because this variable only exists inside the function and you cannot use it outside. For example, consider again the square function:

- + def square(x): y = x * x @@ -62,7 +62,7 @@ print(result)

There is another variation on this theme of local versus global variables. Assignment statements in the local function cannot change variables defined outside the function, without further (discouraged) special syntax. Consider the following codelens example:

- + def powerof(x, p): power = p # Another dumb mistake @@ -96,7 +96,7 @@ print(result) formal parameter will cause a change to the value of the variable that was used as the actual parameter, especially when the two share the same name. But this example demonstrates that that is clearly not how Python operates.

- + def square(x): y = x * x diff --git a/pretext/GeneralIntro/Glossary.ptx b/pretext/GeneralIntro/Glossary.ptx index 012913579..8a5790a26 100644 --- a/pretext/GeneralIntro/Glossary.ptx +++ b/pretext/GeneralIntro/Glossary.ptx @@ -2,10 +2,6 @@
Glossary - - activecode -

A unique interpreter environment that allows Python to be executed from within a web browser.

-
algorithm

A general step by step process for solving a problem.

@@ -20,10 +16,6 @@ modern languages first compile source code into byte code and then interpret the byte code with a program called a virtual machine.

- - codelens -

An interactive environment that allows the user to control the step by step execution of a Python program

-
comment

Information in a program that is meant for other programmers (or anyone diff --git a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx index acb1bfd16..89cab944b 100644 --- a/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx +++ b/pretext/GeneralIntro/SpecialWaystoExecutePythoninthisBook.ptx @@ -53,7 +53,7 @@ print(2 + 3) In codelens you can see and control the step by step progress. Note that the red arrow always points to the next line of code that is going to be executed. The light green arrow points to the line that was just executed.

- + print("My first program adds two numbers, 2 and 3:") print(2 + 3) diff --git a/pretext/Iteration/2DimensionalIterationImageProcessing.ptx b/pretext/Iteration/2DimensionalIterationImageProcessing.ptx index 8e2da7033..f862b0e52 100644 --- a/pretext/Iteration/2DimensionalIterationImageProcessing.ptx +++ b/pretext/Iteration/2DimensionalIterationImageProcessing.ptx @@ -499,7 +499,7 @@ for i in range(5):

Another way to see this in more detail is to examine the behavior with codelens. Step through the iterations to see the flow of control as it occurs with the nested iteration. Again, for every value of i, all of the values of j will occur. You can see that the inner iteration completes before going on to the next pass of the outer iteration.

- + for i in range(5): for j in range(3): diff --git a/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx index cdc423eca..eef5fe495 100644 --- a/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx +++ b/pretext/Iteration/FlowofExecutionofthewhileLoop.ptx @@ -8,7 +8,7 @@

A codelens demonstration is a good way to help you visualize exactly how the flow of control works with the while loop. Try stepping forward and backward through the program by pressing the buttons. You can see the value of count change as the loop iterates through the values from 10 to 0.

- + count = 10 while count > 0: diff --git a/pretext/Iteration/NewtonsMethod.ptx b/pretext/Iteration/NewtonsMethod.ptx index 7a46fbdbe..37de5498f 100644 --- a/pretext/Iteration/NewtonsMethod.ptx +++ b/pretext/Iteration/NewtonsMethod.ptx @@ -43,7 +43,7 @@ prin(betterapprox) enough to the previous one, we can write a function for computing the square root that uses the number of iterations necessary and no more.

This implementation, shown in codelens, uses a while condition to execute until the approximation is no longer changing. Each time through the loop we compute a better approximation using the formula described earlier. As long as the better is different, we try again. Step through the program and watch the approximations get closer and closer.

- + n = 10 approx = 0.5 * n diff --git a/pretext/Iteration/TherangeFunction.ptx b/pretext/Iteration/TherangeFunction.ptx index a3940ade1..d646ee538 100644 --- a/pretext/Iteration/TherangeFunction.ptx +++ b/pretext/Iteration/TherangeFunction.ptx @@ -65,7 +65,7 @@ print(list(range(1, 5)))

Codelens will help us to further understand the way range works. In this case, the variable i will take on values produced by the range function.

- + for i in range(10): print(i) @@ -86,7 +86,7 @@ print(list(range(10, 0, -1)))

Try it in codelens. Do you see why the first two statements produce the same result?

- + for i in range(0, 20, 2): print(i) diff --git a/pretext/Iteration/ThewhileStatement.ptx b/pretext/Iteration/ThewhileStatement.ptx index fc9d1eb6b..72fca7571 100644 --- a/pretext/Iteration/ThewhileStatement.ptx +++ b/pretext/Iteration/ThewhileStatement.ptx @@ -90,7 +90,7 @@ jkI0qdLiJfBzAqWs2;$sR) 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 z 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 +

+ None + +

None, or the NoneType, is a type which represents the absence of a value. + But let's take a step back and think: why is this useful?

+ +

In Python, sometimes we don't want to return anything from a function. However, when we don't + explicitly return anything from a function, Python will implicitly return None. + You could also explicitly return None from a function or return a value, + and then you would have to check if the function returned something or not.

+ +

For the purposes of this class, you should just understand when None appears and why.

+ +

Most commonly when students are learning about strings and lists, us educators see a similar issue, which links back + to sections on mutability. Strings are immutable and lists are mutable, remember?

+ +

When we want to modify a string, we must reassign it, because it's immutable:

+ + +my_string = 'Hello, world!' +new_string = my_string[0:5] +print(new_string) + + + +

Your natural instinct may be to write the same thing with lists:

+ + +my_list = [] +my_list = my_list.append(0) +print(my_list[0]) + + + +

By doing so, you will incur this error:

+ + +print(my_list[0]) +~~~~~~~^^^ +TypeError: 'NoneType' object is not subscriptable + + + +

Frustratingly, your code actually did exactly what you told it to. List functions modify the list directly, because + lists are mutable. Therefore, their functions (such as .append(element)) don't return anything.

+ +

But now we know why: append is actually implicitly returning None. This means that in the previous example, we reassigned my_list + to None, and then we tried to list access element 0 of None, which caused the 'not subscriptable' error, because None isn't a list + and can't have list access done to it.

+ +

The solution is simple: don't reassign the list when calling list functions.

+ + +my_list = [] +my_list.append(0) +print(my_list[0]) + + + +

If you remember nothing else, remember: strings get reassigned, lists don't. This is because + strings are immutable; lists are mutable and their functions don't return anything (they implicitly return None!).

+ + You may be wondering how to tell the difference between functions that return something or not. Sometimes + the name of the method can be a hint (e.g. if it has "set" in the name, it probably won't return, whereas "get" will). + If that doesn't help or you're still curious, you should reference the documentation (whether it's official Python + documentation or for a library). No shame in looking it up! + +

You won't be tested on the information below, but read on for some interesting thoughts on this.

+ +

If you've been around any other programming languages, you may have heard of equivalent ideas like + null, NULL, nullptr, nil, and more. This is such a universal concept + in programming and is hugely frustrating to many programmers as it often represents something that went wrong.

+ +

Fun (or depressing) fact -- the inventor of null actually regrets his invention:

+ +
+ I call it my billion-dollar mistake... At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. +
+ +
+ - Tony Hoare +
+ +

Despite this, None, null, and nil don't seem to be going anywhere anytime soon. :)

+
diff --git a/pretext/Lists/toctree.ptx b/pretext/Lists/toctree.ptx index 96b9c0a70..ef9892fee 100644 --- a/pretext/Lists/toctree.ptx +++ b/pretext/Lists/toctree.ptx @@ -14,6 +14,7 @@ 4 4 4 +4 4 4 diff --git a/pretext/PythonModules/Packages.ptx b/pretext/PythonModules/Packages.ptx new file mode 100644 index 000000000..804312967 --- /dev/null +++ b/pretext/PythonModules/Packages.ptx @@ -0,0 +1,44 @@ + +
+ Packages and Dependencies + + You won't ever need to deal with dependencies in this course unless you are adding modules to your final project. Nonetheless, using packages + (a package is just a collection of Python modules) is a common practice in Python programming that you should at least be aware of. + +

One key tenant of computer science (or anything, for that matter) is that we don't want to reinvent + the wheel if we don't have to. A lot of very smart people have made very useful code, so why not use it?

+ +

The is a website that maintains packages, or code that other people + have written for our use. You might also hear the term dependencies, which describes essentially the same thing: code + that our code depends on.

+ +

PyPI can be accessed with pip, which is the command that you will use when installing dependencies. Pip should come + preinstalled with most Python installations on Mac and Windows.

+ +

Some common packages include: pytest (for testing your code), python-dateutil (for working with dates), flask (for making websites), and more.

+ +

Some common packages for data science include numpy, matplotlib, scipy, pandas and more.

+ +

But this is all sounding like a lot to keep track of, right? How can we ensure consistency between + versions installed on different people's computers?

+ +

requirements.txt is a file we can specify for others to be able install the dependencies + (which is needed to run our code), since others may not have our dependencies installed.

+ +

The following code represents a requirements.txt file that specifies numpy as a dependency:

+ + +numpy==1.26.2 + + + +

Note that dependencies are not installed immediately. For someone to install the requirements which you specify, + they would run the command: pip install -r requirements.txt.

+ +

If you're unsure what version of a dependency you have installed, you can run the command: pip show DEPENDENCY, like pip show numpy. + Somewhat ironically, there are also packages that can autogenerate a requirements.txt file for you.

+ + One additional tip worth mentioning is to always specify the bare minimum requirements your code needs to work. + Dependencies normally have dependencies of their own, so we want to minimize the install time and space taken up + when someone is installing your program's requirements. +
diff --git a/pretext/PythonModules/toctree.ptx b/pretext/PythonModules/toctree.ptx index 77275913f..896c0c70a 100644 --- a/pretext/PythonModules/toctree.ptx +++ b/pretext/PythonModules/toctree.ptx @@ -5,6 +5,7 @@ 4 4 4 +4 4 4 diff --git a/pretext/Selection/Glossary.ptx b/pretext/Selection/Glossary.ptx index 45f9621a2..1c0683c58 100644 --- a/pretext/Selection/Glossary.ptx +++ b/pretext/Selection/Glossary.ptx @@ -69,5 +69,10 @@

One program structure within another, such as a conditional statement inside a branch of another conditional statement.

+ + Pseudocode +

A mix of English and code (in our case, Python) that + programmers use to plan out their programs.

+
diff --git a/pretext/Selection/Pseudocode.ptx b/pretext/Selection/Pseudocode.ptx new file mode 100644 index 000000000..c5ea43ae0 --- /dev/null +++ b/pretext/Selection/Pseudocode.ptx @@ -0,0 +1,102 @@ + +
+ Pseudocode + +

With the introduction of conditionals and branching, our programs are about to become more complex on average. This is a good time to introduce a technique + that will help you plan and structure your programs before you start writing the more complex code. That technique is to use pseudocode.

+ +

Pseudocode is a mix of English and code (in our case, Python) that + programmers use to plan out their programs.

+ +

Writing pseudocode can be helpful for reasons such as:

+
    +
  • It's quicker to write than actual code!
  • +
  • It's readable to more people than actual code, and can still be critiqued like regular code.
  • +
  • It can help you to take on a large or confusing programming task.
  • +
  • It can help you to document your code with comments for yourself and others' readability.
  • +
+ +

There isn't necessarily a right or wrong syntax for pseudocode (except wrong would be if you just wrote the program!). + Your pseudocode and language will probably look different from this, but should be along the same lines.

+ +

Take the following prompt for a problem:

+ +
+ Write a program that takes in a fraction in the format NUMERATOR/DENOMINATOR + from the user and outputs the quotient and the remainder. + If the denominator is 0, print out an error message; if the denominator is anything else, + let the user run the program normally. +
+ +

We can approach this problem first by writing the following pseudocode:

+ + +take user input for fraction +split the user input by "/" +make a variable for numerator, type convert to int +make a variable for denominator, type convert to int +if the denominator is 0, + print an error message +otherwise + make a variable for the numerator divided by denominator + make a variable for the numerator mod denominator + print out both variables + + + +

As you can see, this is basically just a high level outline of your program. It may help you + better see the control flow of your program, or even remind you to do the small things, like + converting your string input to an integer if necessary.

+ +

This pseudocode can then be more readily converted to Python:

+ + + +fraction = input().split('/') +numerator = int(fraction[0]) +denominator = int(fraction[1]) +if denominator == 0: + print("Error, your denominator is 0!") +else: + result = numerator / denominator + remainder = numerator % denominator + print("Division:", result) + print("Remainder:", remainder) + + + +

..and we're done! That's the pseudocode process.

+ +

This won't be something you see often, but let's reverse engineer and see what + existing Python code might look like in pseudocode.

+ + + +character = input() +if character == "Yoda": + print("No! Try not. Do. Or do not. There is no try.") +elif character == "Han Solo": + print("Never tell me the odds!") +elif character == "Obi Wan Kenobi": + print("Use the Force, Luke.") +else: + print("Character not found!") + + + +

We could write the following pseudocode for this program:

+ + +take user input for a Star Wars character +if the character is Yoda, print "No! Try not. Do. Or do not. There is no try." +if the character is Han Solo, print "Never tell me the odds!" +if the character is Obi Wan Kenobi, print "Use the Force, Luke." +in all other cases, print that the character wasn't found + + + +

As you may start to notice, Python is so close to the English language that pseudocode can often + be quickly translated into code.

+ +

Feel free to use pseudocode on exams (for planning before writing code) and in your actual programs.

+
diff --git a/pretext/Selection/toctree.ptx b/pretext/Selection/toctree.ptx index 5a7ff7e66..f39344864 100644 --- a/pretext/Selection/toctree.ptx +++ b/pretext/Selection/toctree.ptx @@ -12,6 +12,7 @@ 4 4 4 +4 4 4 diff --git a/pretext/thinkcspy.ptx b/pretext/thinkcspy.ptx index ffbb4e2c1..b992e2002 100644 --- a/pretext/thinkcspy.ptx +++ b/pretext/thinkcspy.ptx @@ -33,6 +33,8 @@ + + From 1cdd53c7e55158b43c32fc5577ce7422cefcfeae Mon Sep 17 00:00:00 2001 From: Mete Saka <61266931+metesaka@users.noreply.github.com> Date: Sat, 6 Jan 2024 14:14:22 -0700 Subject: [PATCH 73/90] Chapter and section revisions (#3) * Operators modified * string section modified * strings new section * list modified * typos and errors fixed * Update pretext/SimplePythonData/OperatorsandOperands.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/OperatorsandOperands.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/OperatorsandOperands.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/OperatorsandOperands.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/OperatorsandOperands.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/Strings/StringMethods.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/Strings/StringMethods.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * list membership extended * Update pretext/Strings/StringMethods.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Greg's edits fixed * strings and lists question changed * Pure function and its references removed * mutator method extra explanation * function definition added * remove shell and print to shell info * Update pretext/Strings/StringMethods.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/ValuesandDataTypes.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Update pretext/SimplePythonData/ValuesandDataTypes.ptx Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> * Ethan's comments --------- Co-authored-by: Ethan Richards <42894274+ezrichards@users.noreply.github.com> --- pretext/ComplexLogic/toctree.ptx | 3 - pretext/Lists/Glossary.ptx | 5 - pretext/Lists/ListMethods.ptx | 146 +++++++++------ pretext/Lists/StringsandLists.ptx | 71 ++++++- pretext/Lists/toctree.ptx | 2 +- pretext/Selection/ListMembership.ptx | 14 ++ .../SimplePythonData/OperatorsandOperands.ptx | 102 +++++----- .../SimplePythonData/ValuesandDataTypes.ptx | 22 +-- pretext/Strings/StringMethods.ptx | 174 +++--------------- pretext/Strings/StringMethods_optional.ptx | 164 +++++++++++++++++ pretext/Strings/StringsareImmutable.ptx | 2 +- pretext/Strings/toctree.ptx | 6 +- 12 files changed, 424 insertions(+), 287 deletions(-) create mode 100644 pretext/Strings/StringMethods_optional.ptx diff --git a/pretext/ComplexLogic/toctree.ptx b/pretext/ComplexLogic/toctree.ptx index 480ba232e..1f9b76ea8 100644 --- a/pretext/ComplexLogic/toctree.ptx +++ b/pretext/ComplexLogic/toctree.ptx @@ -9,8 +9,5 @@ 4 4 4 -4 -4 -4 4 diff --git a/pretext/Lists/Glossary.ptx b/pretext/Lists/Glossary.ptx index 39204b03a..662f8d442 100644 --- a/pretext/Lists/Glossary.ptx +++ b/pretext/Lists/Glossary.ptx @@ -62,11 +62,6 @@ patterns and algorithms that form your toolkit. Patterns often correspond to your mental chunking.

- - pure function -

A function which has no side effects. Pure functions only make changes - to the calling program through their return values.

-
sequence

Any of the data types that consist of an ordered collection of elements, with diff --git a/pretext/Lists/ListMethods.ptx b/pretext/Lists/ListMethods.ptx index 7fb739c5e..175f25daa 100644 --- a/pretext/Lists/ListMethods.ptx +++ b/pretext/Lists/ListMethods.ptx @@ -1,49 +1,16 @@

List Methods -

The dot operator can also be used to access built-in methods of list objects. - append is a list method which adds the argument passed to it to the end of - the list. Continuing with this example, we show several other list methods. Many of them are - easy to understand.

- - -mylist = [] -mylist.append(5) -mylist.append(27) -mylist.append(3) -mylist.append(12) -print(mylist) -mylist.insert(1, 12) # Insert 12 at pos 1, shift other items up -print(mylist) -print(mylist.count(12)) # How many times is 12 in mylist? - -print(mylist.index(3)) # Find index of first 3 in mylist -print(mylist.count(5)) - -mylist.reverse() -print(mylist) - -mylist.sort() -print(mylist) +

The dot operator can also be used to access built-in methods of list objects. + As you remember, unlike strings, lists are mutable. As a consequence, list methods can have different behaviors than string methods. Let's look at these.

+
    +
  • Return Type Methods: These methods work the same way as string methods: they give us a value but keep the original list the same.
  • +
  • Mutating Methods: These methods modify the list but do not return anything. Because of this, we shouldn't use these methods on the right hand side of assignment (we shouldn't assign them to a variable).
  • +
  • Hybrid Methods: These methods behave as both mutating and return type methods. They change the list and also return a value.
  • +
-mylist.remove(5) # Removes the first 12 in the list -print(mylist) - -lastitem = mylist.pop() # Removes and returns the last item of the list -print(lastitem) -print(mylist) - -
-

There are two ways to use the pop method. The first, with no parameter, will remove and return the - last item of the list. If you provide a parameter for the position, pop will remove and return the - item at that position. Either way the list is changed.

-

The following table provides a summary of the list methods shown above. The column labeled - result gives an explanation as to what the return value is as it relates to the new value of the list. The word - mutator means that the list is changed by the method but nothing is returned (actually None is returned). A hybrid method is one that not only changes the list but also returns a value as its result. Finally, if the result is simply a return, then the list - is unchanged by the method.

-

Be sure - to experiment with these methods to gain a better understanding of what they do.

+

The following table provides a summary of the list methods shown above. The column labeled behavior gives an explanation as to what the return value is as it relates to the new value of the list.

@@ -54,7 +21,7 @@ print(mylist) Parameters - Result + Behavior Description @@ -68,7 +35,7 @@ print(mylist) item - mutator + mutating Adds a new item to the end of a list @@ -82,7 +49,7 @@ print(mylist) position, item - mutator + mutating Inserts a new item at the position given @@ -124,7 +91,7 @@ print(mylist) none - mutator + mutating Modifies a list to be sorted @@ -138,7 +105,7 @@ print(mylist) none - mutator + mutating Modifies a list to be in reverse order @@ -155,7 +122,7 @@ print(mylist) return idx - Returns the position of first occurrence of item + Returns the position of first occurrence of item, error if not found @@ -180,7 +147,7 @@ print(mylist) item - mutator + mutating Removes the first occurrence of item @@ -188,23 +155,94 @@ print(mylist)
-

Details for these and others - can be found in the Python Documentation.

-

It is important to remember that methods like append, sort, - and reverse all return None. This means that re-assigning mylist to the result of sorting mylist will result in losing the entire list. Calls like these will likely never appear as part of an assignment statement (see line 8 below).

- + + + +

Here are some examples on these methods. Be sure to experiment with them to gain a better understanding of what they do. You are expected to be comfortable using these methods!

+ + + +# Let's create a list and fill it with some values mylist = [] mylist.append(5) mylist.append(27) mylist.append(3) mylist.append(12) print(mylist) + + + +

Another way to add items:

-mylist = mylist.sort() #probably an error + + +mylist = [5, 27, 3, 12] +mylist.insert(1, 12) # Insert 12 at pos 1, shift other items up +print(mylist) + + + +

Some return type methods:

+ + + +mylist = [5, 27, 3, 12] +print(mylist.count(12)) # How many times is 12 in mylist? +print(mylist.index(3)) # Find index of first 3 in mylist +print(mylist) # mylist is unchanged as count and index are return type methods + + + +

Some mutating methods:

+ + + +mylist = [5, 27, 3, 12] +mylist.reverse() +print(mylist) + +mylist.sort() +print(mylist) + +mylist.remove(5) # Removes the value 5 from the list +print(mylist) + +my_second_list = mylist.append(5) # We shouldn't assign the result of a mutating method to a variable! +print(my_second_list) # It will be None + + + +

It is important to remember that methods like append, sort, + and reverse all return None. This means that re-assigning mylist + to the result of sorting mylist will result in losing the entire list.

+ + +

Some hybrid methods:

+ + + + +mylist = [5, 27, 3, 12] +lastitem = mylist.pop() # Removes and returns the last item of the list +print(lastitem) +print(mylist) + +seconditem = mylist.pop(1) # Removes and returns the item at index 1 +print(seconditem) + +mylist.pop() # Remember that pop is a hybrid method print(mylist) +

Notice that there are two ways to use the pop method. The first, with no parameter, will remove and return the + last item of the list. If you provide a parameter for the position, pop will remove and return the + item at that position. Either way the list is changed. Hybrid methods will also change + the list without assignment to a variable, as shown with the last example above.

+ +

Details for these methods and others + can be found in the Python Documentation.

+

Check your understanding

diff --git a/pretext/Lists/StringsandLists.ptx b/pretext/Lists/StringsandLists.ptx index c3c62a75f..9bb57321b 100644 --- a/pretext/Lists/StringsandLists.ptx +++ b/pretext/Lists/StringsandLists.ptx @@ -10,16 +10,28 @@ song = "The rain in Spain..." wds = song.split() print(wds) +

An optional argument called a delimiter can be used to specify which - characters to use as word boundaries. The following example uses the string - ai as the delimiter:

+ characters to use as word boundaries.

-song = "The rain in Spain..." +song = "The rain, and the flood in Spain..." + +#These are the same as the default is to split on whitespace: +print(song.split()) +print(song.split(' ')) + +#If we want to split on something else, we can do that too: +abc = song.split(',') +print(abc) wds = song.split('ai') print(wds) + +# Notice that the split is a string method, so it does not modify the original string. +print(song) +

Notice that the delimiter doesn't appear in the result.

@@ -40,6 +52,51 @@ print("".join(wds))

The list that you glue together (wds in this example) is not modified. Also, you can use empty glue or multi-character strings as glue.

+ +

+ index Method in Lists and Strings +

+

One important thing to note is that even though index methods is named the same in the context of strings and lists, they behave differently. +With strings, the index method looks for a substring (or a character), and returns the first instance of that character. +However, with lists, the index method looks for an element and returns the first instance of that element.

+ + + + + +my_str = "To a great mind, nothing is little,' remarked Holmes, sententiously." +print(my_str.index("great")) # Finds the substring "great" in my_str, expected result is 5 +print(my_str.index("n")) # Finds the character "n" in my_str, expected result is 13 (first occurence) + + + +

What happens when I split the string to a list?

+ + + +my_str = "To a great mind, nothing is little,' remarked Holmes, sententiously." +my_list = my_str.split() +print(my_list) +print(my_list.index("great")) # Finds the element "great" in my_list, expected result is 2 +print(my_list.index("n")) # "n" is NOT an element in my_list, expected result is an error + + + +

BONUS: Check this example after reading the next section (List Type Conversion Function) and spot the difference!

+ + + +my_str = "To a great mind, nothing is little,' remarked Holmes, sententiously." + +char_by_char = list(my_str) +print(char_by_char) +print(char_by_char.index("n")) # Finds the element "n" in char_by_char, expected result is 13 +print(char_by_char.index("great")) # "great" is NOT an element in char_by_char, expected result is an error + + + + +

Check your understanding

@@ -51,8 +108,10 @@ print("".join(wds)) myname = "Edgar Allan Poe" namelist = myname.split() init = "" -for aname in namelist: - init = init + aname[0] +str1 = namelist[0] +str2 = namelist[1] +str3 = namelist[2] +init = init + str1[0] + str2[0] + str3[0] print(init) @@ -79,7 +138,7 @@ print(init)

EAP

- Yes, split creates a list of the three names. The for loop iterates through the names and creates a string from the first characters. + Yes, split creates a list of the three names. diff --git a/pretext/Lists/toctree.ptx b/pretext/Lists/toctree.ptx index ef9892fee..47cde51f7 100644 --- a/pretext/Lists/toctree.ptx +++ b/pretext/Lists/toctree.ptx @@ -11,8 +11,8 @@ 4 4 4 -4 4 +4 4 4 4 diff --git a/pretext/Selection/ListMembership.ptx b/pretext/Selection/ListMembership.ptx index d0947ef96..a5893b443 100644 --- a/pretext/Selection/ListMembership.ptx +++ b/pretext/Selection/ListMembership.ptx @@ -11,9 +11,23 @@ print("apple" in fruit) print("pear" in fruit) + +

Remember that in and not in only checks for membership in the top level of a list.

+ + + +my_list = ["apple", "orange", "banana", "cherry", ["pear", "kiwi"]] +print("pear" in my_list) # prints False because "pear" is in a sublist +print("g" in my_list) # prints False because "g" is not an member in my_list by itself + + + + +

Check your understanding

+

What is printed by the following statements?

diff --git a/pretext/SimplePythonData/OperatorsandOperands.ptx b/pretext/SimplePythonData/OperatorsandOperands.ptx index fa7b0ae40..88334eba6 100644 --- a/pretext/SimplePythonData/OperatorsandOperands.ptx +++ b/pretext/SimplePythonData/OperatorsandOperands.ptx @@ -14,76 +14,74 @@ hour * 60 + minute minute / 60 5 ** 2 (5 + 9) * (15 - 7) -

The tokens +, -, and *, and the use of parenthesis for grouping, - mean in Python what they mean in mathematics. The asterisk (*) is the - token for multiplication, and ** is the token for exponentiation. - Addition, subtraction, multiplication, and exponentiation all do what you - expect.

+ +

Python uses special characters called operators that perform the following operations:

+
    +
  • + addition
  • +
  • - subtraction
  • +
  • * multiplication
  • +
  • / division
  • +
  • ** exponentiation
  • +
  • () grouping
  • +
  • // integer division (round down division)
  • +
  • % modulo (remainder)
  • +
+ +

There are several other operators that we will learn in future chapters. But these are the ones that you're going to need more or less all of your assignments!

+ -print(2 + 3) -print(2 - 3) -print(2 * 3) -print(2 ** 3) -print(3 ** 2) +print(2 + 3) # Addition operator, expected result is 5 +print(2 - 3) # Subtraction operator, expected result is -1 +print(2 * 3) # Multiplication operator, expected result is 6 +print(5 / 3) # Division operator, expected result is 1.6666666666666666 +print(3 ** 2) # Exponentiation operator, expected result is 9 +print(3*(2+4)) # Grouping operator, changes the precedence expected result is 18 -

When a variable name appears in the place of an operand, it is replaced with - the value that it refers to before the operation is performed. - For example, what if we wanted to convert 645 minutes into hours. - In Python 3, division is denoted by the operator token / which always evaluates to a floating point - result.

+ +

The first six operators have functionality that you're most probably pretty familiar with! On the other hand, we have two more operators that are used frequently in programming but not that much in math classes. +These are integer division, and modulo.

+ +

In the previous example 5 / 3 resulted 1.66666666 . This is because / always returns a floating point result. However, in certain situations, we need an integer result from division. +Integer division, or the // operator, divides the number, but rounds it down to the nearest integer. So for the previous example, 5 // 3 will result 1

+ +

The modulo operator, % yields + the remainder when the first operand is divided by the second (that's why you can also remember it as remainder operator). For example, 5 % 3 will result 2 as 5 = 3 * 1 + 2 .

+ -minutes = 645 -hours = minutes / 60 -print(hours) +print(5//3) # Integer division operator, expected result is 1 +print(60//7) # Integer division operator, expected result is 8 +print(50//2) # Integer division operator works same as division operator when the result is integer + +print(5%3) # Modulo operator, expected result is 2 +print(60%7) # Modulo operator, expected result is 4 +print(4%2) # Modulo operator, expected result is 0 -

What if, on the other hand, we had wanted to know how many whole hours there - are and how many minutes remain. To help answer this question, Python gives us a second flavor of - the division operator. This version, called integer division, uses the token - //. It always truncates its result down to the next smallest integer (to - the left on the number line).

+ +

When a variable name appears in place of an operand, + python substitutes that variable name with its assigned value. For example, what if we wanted to convert 645 minutes into hours? +

-print(7 / 4) -print(7 // 4) - minutes = 645 -hours = minutes // 60 +hours = minutes / 60 print(hours) - -print(6//4) -print(-6//4) -

Pay particular attention to the first two examples above. Notice that the result of floating point division - is 1.75 but the result of the integer division is simply 1. - Take care that you choose the correct flavor of the division operator. If - you're working with expressions where you need floating point values, use the - division operator /. If you want an integer result, use //. -

-

The modulus operator, sometimes also called the remainder operator or integer remainder operator works on integers (and integer expressions) and yields - the remainder when the first operand is divided by the second. In Python, the - modulus operator is a percent sign (%). The syntax is the same as for other - operators.

- - -quotient = 7 // 3 # This is the integer division operator -print(quotient) -remainder = 7 % 3 -print(remainder) - - -

In the above example, 7 divided by 3 is 2 when we use integer division and there is a remainder of 1 when we use the modulus operator.

-

The modulus operator turns out to be surprisingly useful. For example, you can + + + +

The modulo operator turns out to be surprisingly useful. For example, you can check whether one number is divisible by another—if x % y is zero, then x is divisible by y. Also, you can extract the right-most digit or digits from a number. For example, x % 10 yields the right-most digit of x (in base 10). Similarly x % 100 yields the last two digits.

-

Finally, returning to our time example, the remainder operator is extremely useful for doing conversions, say from seconds, + +

The remainder operator is extremely useful for doing conversions, say from seconds, to hours, minutes and seconds. If we start with a number of seconds, say 7684, the following program uses integer division and remainder to convert to an easier form. Step through it to be sure you understand how the division and remainder operators are being used to compute the correct values.

@@ -96,6 +94,8 @@ print(remainder) secs_finally_remaining = secs_still_remaining % 60 + +

Check your understanding

diff --git a/pretext/SimplePythonData/ValuesandDataTypes.ptx b/pretext/SimplePythonData/ValuesandDataTypes.ptx index e16efe05d..22b6ae15e 100644 --- a/pretext/SimplePythonData/ValuesandDataTypes.ptx +++ b/pretext/SimplePythonData/ValuesandDataTypes.ptx @@ -26,21 +26,13 @@ print("Hello, World")

When we show the value of a string using the print function, such as in the third example above, the quotes are not present in the output. The value of the string is the sequence of characters inside the quotes. The quotes are only necessary to help Python know what the value is.

-

You may have used function notation in a math class, like y = f(x), likely only for functions that act on a single numeric value, and produce a single numeric value. Python has no such restrictions: Inputs and outputs may be of any type.

-

In the Python shell, it is not necessary to use the print function to see the values shown above. The shell evaluates the Python function and automatically prints the result. For example, consider the shell session shown below. When - we ask the shell to evaluate type("Hello, World!"), it responds with the appropriate answer and then goes on to - display the prompt for the next use.

-
Python 3.1.2 (r312:79360M, Mar 24 2010, 01:33:18)
-[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
-Type "help", "copyright", "credits" or "license" for more information.
->>> type("Hello, World!")
-<class 'str'>
->>> type(17)
-<class 'int'>
->>> "Hello, World"
-'Hello, World'
->>>
-

Note that in the last example, we simply ask the shell to evaluate the string Hello, World. The result is as you might expect, the string itself.

+

In programming, a function is a subroutine, designed to perform a specific task. When you "call" a function, you're asking it to execute its task. + Functions can take in information, known as arguments, work with that information, and then often return a result. + For example, print() is a function which takes in a single string argument between the parentheses and performs the task: + Printing the string argument we provided to the terminal.

+ +

You will get more familiar with functions (and design your own functions!) in the following weeks.

+

Continuing with our discussion of data types, numbers with a decimal point belong to a class called float, because these numbers are represented in a format called floating-point. At this stage, you can treat the words class and type diff --git a/pretext/Strings/StringMethods.ptx b/pretext/Strings/StringMethods.ptx index 0dc0a77bd..c91d81551 100644 --- a/pretext/Strings/StringMethods.ptx +++ b/pretext/Strings/StringMethods.ptx @@ -1,24 +1,27 @@

String Methods -

We previously used a few functions like print() and input(). A method is a function that is attached to a specific Python object. +

We previously used a few functions like print() and len() where we place the variable inside the parentheses such as len(my_str). On the other hand, a method is a function that is attached to a specific Python object. To access this function, we write the object, then a dot ., and then the name of the method. The "dot notation" is the way we connect the name of an object to the name of a method - it can perform. For example, we can write ss.upper() when we wanted the string ss to perform the upper() method to create an upper-case version of itself.

-

Remember that Strings are objects. Each string instance has its own attributes and methods. The most important attribute of the string is the collection of characters. There are a wide variety of methods. Try the following program.

+ it can perform. For example, we can write my_str.upper() when we want the string my_str to perform the upper() method to create an upper-case version of itself.

+ + +

Remember that strings are immutable. Therefore, all string methods give us a new string and must be assigned to a new variable. The original string is unchanged.

+ -ss = "Hello, World" -print(ss.upper()) - -tt = ss.lower() -print(tt) - +my_str = "Hello, World" +my_str.upper() +print(my_str) # my_str is unchanged! +print(my_str.upper()) #Gives us the new string, we can print it or assign it to a variable +my_new_str = my_str.upper() +print(my_new_str) +

In this example, upper is a method that can be invoked on any string object to create a new string in which all the - characters are in uppercase. lower works in a similar fashion changing all characters in the string - to lowercase. (The original string ss remains unchanged. A new string tt is created.)

-

In addition to upper and lower, the following table provides a summary of some other useful string methods. There are a few activecode examples that follow so that you can try them out.

+ characters are in uppercase.

+

In addition to upper, the following table provides some useful string methods.

@@ -54,50 +57,6 @@ print(tt) Returns a string in all lowercase - - - capitalize - - - none - - - Returns a string with first character capitalized, the rest lower - - - - - strip - - - none - - - Returns a string with the leading and trailing whitespace removed - - - - - lstrip - - - none - - - Returns a string with the leading whitespace removed - - - - - rstrip - - - none - - - Returns a string with the trailing whitespace removed - - count @@ -120,61 +79,6 @@ print(tt) Replaces all occurrences of old substring with new - - - center - - - width - - - Returns a string centered in a field of width spaces - - - - - ljust - - - width - - - Returns a string left justified in a field of width spaces - - - - - rjust - - - width - - - Returns a string right justified in a field of width spaces - - - - - find - - - item - - - Returns the leftmost index where the substring item is found, or -1 if not found - - - - - rfind - - - item - - - Returns the rightmost index where the substring item is found, or -1 if not found - - index @@ -183,58 +87,30 @@ print(tt) item - Like find except causes a runtime error if item is not found - - - - - rindex - - - item - - - Like rfind except causes a runtime error if item is not found + Returns the leftmost index where the substring item is found, or error if not found

You should experiment with these - methods so that you understand what they do. Note once again that the methods that return strings do not - change the original. You can also consult the Python documentation for strings.

+ methods so that you understand what they do. Note once again that the methods that return strings do not + change the original.

-ss = " Hello, World " +ss = "Hello, World" els = ss.count("l") print(els) -print("***" + ss.strip() + "***") -print("***" + ss.lstrip() + "***") -print("***" + ss.rstrip() + "***") - news = ss.replace("o", "***") print(news) - - - - -food = "banana bread" -print(food.capitalize()) - -print("*" + food.center(25) + "*") -print("*" + food.ljust(25) + "*") # stars added to show bounds -print("*" + food.rjust(25) + "*") - -print(food.find("e")) -print(food.find("na")) -print(food.find("b")) - -print(food.rfind("e")) -print(food.rfind("na")) -print(food.rfind("b")) +food = "banana Bread" +print(food.lower()) print(food.index("e")) +print(food.index("na")) #finds the index of the first occurence of "na" +print(food.index("b")) +print(food.index("B")) #remember that python is case sensitive!

@@ -293,7 +169,7 @@ print(s[1] * s.index("n"))

yyyyy

- Yes, s[1] is y and the index of n is 5, so 5 y characters. It is important to realize that the index method has precedence over the repetition operator. Repetition is done last. + Yes, s[1] is y and the index of n is 5, so 5 y characters. It is important to realize that the index method has precedence over the repetition operator. diff --git a/pretext/Strings/StringMethods_optional.ptx b/pretext/Strings/StringMethods_optional.ptx new file mode 100644 index 000000000..4d7b9edbb --- /dev/null +++ b/pretext/Strings/StringMethods_optional.ptx @@ -0,0 +1,164 @@ + +
+ Some Extra String Methods (Optional) + +

In addition to what we have seen in the previous section, the following table provides a summary of some other string methods. You don't have to memorize them.

+ + + + + Method + + + Parameters + + + Description + + + + + capitalize + + + none + + + Returns a string with first character capitalized, the rest lower + + + + + strip + + + none + + + Returns a string with the leading and trailing whitespace removed + + + + + lstrip + + + none + + + Returns a string with the leading whitespace removed + + + + + rstrip + + + none + + + Returns a string with the trailing whitespace removed + + + + + center + + + width + + + Returns a string centered in a field of width spaces + + + + + ljust + + + width + + + Returns a string left justified in a field of width spaces + + + + + rjust + + + width + + + Returns a string right justified in a field of width spaces + + + + + rfind + + + item + + + Returns the rightmost index where the substring item is found, or -1 if not found + + + + + find + + + item + + + Like index except returns -1 if item is not found + + + + + rindex + + + item + + + Like rfind except causes a runtime error if item is not found + + + +
+

You should experiment with these + methods so that you understand what they do. Note once again that the methods that return strings do not + change the original. You can also consult the Python documentation for strings.

+ + +ss = " Hello, World " + +print("***" + ss.strip() + "***") +print("***" + ss.lstrip() + "***") +print("***" + ss.rstrip() + "***") + + + + +food = "banana bread" +print(food.capitalize()) + +print("*" + food.center(25) + "*") +print("*" + food.ljust(25) + "*") # stars added to show bounds +print("*" + food.rjust(25) + "*") + +print(food.index("e")) +print(food.index("na")) + +print(food.rfind("e")) +print(food.rfind("na")) +print(food.rfind("b")) + + + + + + +
diff --git a/pretext/Strings/StringsareImmutable.ptx b/pretext/Strings/StringsareImmutable.ptx index 5a6ab7a82..4eb55ff90 100644 --- a/pretext/Strings/StringsareImmutable.ptx +++ b/pretext/Strings/StringsareImmutable.ptx @@ -1,7 +1,7 @@
Strings are Immutable -

One final thing that makes strings different from some other Python collection types is that +

One important thing that makes strings different from some other Python collection types is that you are not allowed to modify the individual characters in the collection. It is tempting to use the [] operator on the left side of an assignment, with the intention of changing a character in a string. For example, in the following code, we would like to change the first letter of greeting.

diff --git a/pretext/Strings/toctree.ptx b/pretext/Strings/toctree.ptx index 5e66dcaed..a45d88628 100644 --- a/pretext/Strings/toctree.ptx +++ b/pretext/Strings/toctree.ptx @@ -5,11 +5,13 @@ 4 4 4 -4 4 4 -4 4 +4 +4 4 4 +4 + From 6b21168b0c3243abea66db80c0bd38b03afc202f Mon Sep 17 00:00:00 2001 From: robotuw Date: Sat, 6 Jan 2024 15:12:44 -0700 Subject: [PATCH 74/90] Minor typo fixes and wording changes --- pretext/AdditionalTopics/BigO.ptx | 6 +++--- pretext/AdditionalTopics/DataScience.ptx | 2 +- pretext/AdditionalTopics/SearchSortAlgorithms.ptx | 6 +++--- pretext/Lists/None.ptx | 6 ++---- pretext/PythonModules/Packages.ptx | 4 ++-- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pretext/AdditionalTopics/BigO.ptx b/pretext/AdditionalTopics/BigO.ptx index 314e274f6..01735d235 100644 --- a/pretext/AdditionalTopics/BigO.ptx +++ b/pretext/AdditionalTopics/BigO.ptx @@ -8,7 +8,7 @@ some of the things that would need to be considered.

-

To simplify this issue, we'll give up trying to estimate exactly how long a program will run, and instead look at the biggest factor that affect +

To simplify this issue, we'll give up trying to estimate exactly how long a program will run, and instead look at the biggest factor that affects existing code: the size of the input. If we wrote a program that ran for 60 seconds on 100 megabytes of input data, how should we expect the program to react to 200 megabytes of input data? Maybe it would run in 120 seconds (twice the data for twice the run time)? Maybe it would still run in 60 seconds, assuming that extra data isn't used. Or maybe the program would run for far longer. The issue is that we don't know what the relationship is between the size @@ -50,7 +50,7 @@ else:

In this program, the size of the input doesn't matter as much as whether the input string contains a letter "a" or not. If it does, the program runs forever. If it doesn't, the program ends almost immediately. How do we reconcile this with our Big O notation? The answer is to be a pessimist. We adopt the assumption that everything that can happen to slow down our program will happen. In the code above, we assume that the input ALWAYS will contain an "a". This assumption is broadly - known as the "worst case". Big O notation uses this assumption in every instance you will see it (at least in this class).

+ known as the "worst case". Big O notation uses this assumption by default in every instance you will see it (at least in this class). Any other case besides "worst" will be labeled.

Let's look at some more examples:

@@ -82,7 +82,7 @@ def example_func(n):

This figure shows complexities as a graph and which ones are considered "desirable" or at least "acceptable". Context mostly determines if these are "good" terms or not, but do strive to never write something worse than O(n^3)!

-

It may be difficult to appreciate the implications of these terms when first seeing them. Let's say we have an algorithm with the following complexities, but they +

It may be difficult to appreciate the implications of these terms when first seeing them. Let's say we have a set of algorithms with the following complexities, but they all run with the same time (1 milliseconds) for n = 10. This table shows what will happen if we increase the size of the input:

diff --git a/pretext/AdditionalTopics/DataScience.ptx b/pretext/AdditionalTopics/DataScience.ptx index 99569ff9f..79a7e19cb 100644 --- a/pretext/AdditionalTopics/DataScience.ptx +++ b/pretext/AdditionalTopics/DataScience.ptx @@ -20,7 +20,7 @@

Obtaining the data: We live in a time where data is more abundant then ever before. Getting a hold of data can involve gathering it yourself, purchasing it, or taking advantage of the many, many sites online now which have a plethora of data - available for free (and sometimes paid) use. if you are getting your data from some 3rd party, it will likely come in a .csv, .json, or SQL database format.

+ available for free (and sometimes paid) use. If you are getting your data from some 3rd party, it will likely come in a .csv, .json, or SQL database format.

Cleaning the data: This can vary, but ultimately you need to prepare your data in a way that makes it easily usable in the next steps. Often data starts out "noisy" or contains errors. In this step you may diff --git a/pretext/AdditionalTopics/SearchSortAlgorithms.ptx b/pretext/AdditionalTopics/SearchSortAlgorithms.ptx index 5f8dbfb4d..6b1f8f10b 100644 --- a/pretext/AdditionalTopics/SearchSortAlgorithms.ptx +++ b/pretext/AdditionalTopics/SearchSortAlgorithms.ptx @@ -28,11 +28,11 @@ for element in my_list:

Linear search has a best case complexity of O(1), average case of O(n), and worst case of O(n). - Remember from the Big O section: in the best case, the element we're looking for is the first element. But in the + In the best case, the element we're looking for is the first element. But in the average and worst cases, we will have to look through some n elements.

-

Binary search is an improvement upon linear search. Binary search splits the searched list in half, - and if the number we're searching for is less than that number, we know it must be in the left half of the list; +

Binary search is an improvement upon linear search. Binary search splits the searched list in half and looks at the middle value. + If the number we're searching for is less than that value, we know it must be in the left half of the list; if it's greater, we know it must be in the right half of the list, and we can repeat this process on smaller portions of the list until we find the number.

Binary search has a best case complexity of O(1), average case of O(logn), and worst case of O(logn).

diff --git a/pretext/Lists/None.ptx b/pretext/Lists/None.ptx index 6a331270e..7d5e6a10d 100644 --- a/pretext/Lists/None.ptx +++ b/pretext/Lists/None.ptx @@ -6,9 +6,7 @@ But let's take a step back and think: why is this useful?

In Python, sometimes we don't want to return anything from a function. However, when we don't - explicitly return anything from a function, Python will implicitly return None. - You could also explicitly return None from a function or return a value, - and then you would have to check if the function returned something or not.

+ explicitly return anything from a function, Python will implicitly return None.

For the purposes of this class, you should just understand when None appears and why.

@@ -59,7 +57,7 @@ print(my_list[0])

If you remember nothing else, remember: strings get reassigned, lists don't. This is because - strings are immutable; lists are mutable and their functions don't return anything (they implicitly return None!).

+ strings are immutable; lists are mutable and most of their functions don't return anything (meaning they implicitly return None!).

You may be wondering how to tell the difference between functions that return something or not. Sometimes the name of the method can be a hint (e.g. if it has "set" in the name, it probably won't return, whereas "get" will). diff --git a/pretext/PythonModules/Packages.ptx b/pretext/PythonModules/Packages.ptx index 804312967..adf216ce9 100644 --- a/pretext/PythonModules/Packages.ptx +++ b/pretext/PythonModules/Packages.ptx @@ -22,8 +22,8 @@

But this is all sounding like a lot to keep track of, right? How can we ensure consistency between versions installed on different people's computers?

-

requirements.txt is a file we can specify for others to be able install the dependencies - (which is needed to run our code), since others may not have our dependencies installed.

+

requirements.txt is a file we can specify for others to be able to easily install dependencies + (which are needed to run our code), since others may not have them installed on their own computers yet.

The following code represents a requirements.txt file that specifies numpy as a dependency:

From 68cc7c294319b2e905e717bb8d40c2275103311b Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:11:06 -0600 Subject: [PATCH 75/90] Update pretext and broken chapter --- .gitignore | 105 ++++++++++++++++++++ README.rst | 2 +- pretext/Debugging/KnowyourerrorMessages.ptx | 4 +- requirements.txt | 3 +- 4 files changed, 110 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 7748bbf5d..c9179e8cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# (delete the above line to manage this file manually) __pycache__/ build_info build @@ -19,3 +20,107 @@ beta output published pdf +venv/ +cli.log + +# Boilerplate list of files in a PreTeXt project for git to ignore +# ensure this file is tracked +!.gitignore + +# don't track unpublished builds or stage (note: Runestone uses `published`) +output +published + +# don't track assets generated from source +generated-assets + +# don't track the executables.ptx file +executables.ptx + +# don't track node packages +node_modules + +# don't track error logs +.error_schema.log +logs + +# don't track OS related files (windows/macos/linux) +.DS_Store +.DS_Store? +._* +.AppleDouble +.LSOverride +.Spotlight-V100 +.Trashes +Icon +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +*.lnk +*.cab +*.msi +*.msix +*.msm +*.msp +[Dd]esktop.ini +.directory +.fuse_hidden* +.Trash-* +.nfs* + +# Don't include VSCode generated files +.vscode +*.code-workspace + +# Don't inlucde SublimeText files +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +*.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +# Don't include Dropbox settings and caches +.dropbox +.dropbox.attr +.dropbox.cache + +# Don't track codechat config (will be generated automatically) +codechat_config.yaml + +# Don't track deprecated workflows +.github/workflows/deploy.yml +.github/workflows/test-build.yml diff --git a/README.rst b/README.rst index c63c49ea5..db95ae659 100644 --- a/README.rst +++ b/README.rst @@ -31,7 +31,7 @@ Building with PreTeXt --------------------- 1. Create a virtual environment -2. pip install pretextbook +2. pip install pretext 3. To build run: pretext build web 4. pretext view html diff --git a/pretext/Debugging/KnowyourerrorMessages.ptx b/pretext/Debugging/KnowyourerrorMessages.ptx index 8518fd9b0..4bf31b6ec 100644 --- a/pretext/Debugging/KnowyourerrorMessages.ptx +++ b/pretext/Debugging/KnowyourerrorMessages.ptx @@ -44,7 +44,7 @@ print(final_time_int) Python interpreter. The interpreter in activecode is limited in many ways, but it is intended for beginners, including the wording chosen to describe errors.

- +

In writing and using this book over the last few years we have collected a lot of statistics about the programs in this book. Here are some statistics about error messages for the exercise we have been looking at.

diff --git a/requirements.txt b/requirements.txt index 30f82a1cd..13dd24cd8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -pretext == 1.6.0 \ No newline at end of file +# +pretext == 2.6.2 From 90dd815c3d97921d212ea41132a4883b33746771 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:21:08 -0600 Subject: [PATCH 76/90] Update README --- README.rst => README.md | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) rename README.rst => README.md (66%) diff --git a/README.rst b/README.md similarity index 66% rename from README.rst rename to README.md index db95ae659..8a1731850 100644 --- a/README.rst +++ b/README.md @@ -1,5 +1,4 @@ -How to Think Like a Computer Scientist: Interactive Edition -=========================================================== +# How to Think Like a Computer Scientist: Interactive Edition This project began with the original How to Think Like a Computer Scientist text by Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris Meyers, and Dario Mitchell. Since 2011 Brad Miller, David Ranum, Barbara Ericson, Mark Guzdial, and many others have built on the text making it interactive. @@ -17,29 +16,15 @@ works. .. image:: https://travis-ci.org/RunestoneInteractive/thinkcspy.svg?branch=master :target: https://travis-ci.org/RunestoneInteractive/thinkcspy - -Getting Started -=============== - -We have tried to make it as easy as possible for you to build and use this book. - -You can see and read this book online at `runestone.academy `_ .. important:: The restructuredText version of this book is deprecated! Building with PreTeXt --------------------- -1. Create a virtual environment +1. Create and activate a virtual environment 2. pip install pretext 3. To build run: pretext build web -4. pretext view html +4. pretext view Note: The pretext sources are in the pretext folder, we will keep the _sources folder until we are 100% sure that the book has been converted correctly and as thoroughly as possible. - -Building for Production on a Runestone Server ---------------------------------------------- - -1. clone this repo to `httlacs` instead of `thinkcspy` -2. Run `rsmanage addcourse` and add `httlacs` as course name and base course name -3. Run `rsmanage build --ptx httlacs` From d5fd0a9b6a3f768e1f444661061d048eca84d7b0 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:25:39 -0600 Subject: [PATCH 77/90] Update README --- README.md | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 8a1731850..377decf3b 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,19 @@ -# How to Think Like a Computer Scientist: Interactive Edition +# How to Think Like a Computer Scientist: Mines Edition +This is a fork of the original [thinkcspy](https://github.com/runestoneinteractive/thinkcspy) made for Colorado School of Mines CSCI128: -This project began with the original How to Think Like a Computer Scientist text by Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris Meyers, and Dario Mitchell. Since 2011 Brad Miller, David Ranum, Barbara Ericson, Mark Guzdial, and many others have built on the text making it interactive. +> This project began with the original How to Think Like a Computer Scientist text by Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris Meyers, and Dario Mitchell. Since 2011 Brad Miller, David Ranum, Barbara Ericson, Mark Guzdial, and many others have built on the text making it interactive. -Programming is not a "spectator sport". It is something you do, -something you participate in. It would make sense, then, -that the book you use to learn programming should allow you to be active. -That is our goal. +> Programming is not a "spectator sport". It is something you do, something you participate in. It would make sense, then, that the book you use to learn programming should allow you to be active. That is our goal. -This book is meant to provide you with an interactive experience as you learn -to program in Python. You can read the text, watch videos, -and write and execute Python code. In addition to simply executing code, -there is a unique feature called 'codelens' that allows you to control the -flow of execution in order to gain a better understanding of how the program -works. + > This book is meant to provide you with an interactive experience as you learn to program in Python. You can read the text, watch videos, and write and execute Python code. In addition to simply executing code, there is a unique feature called 'codelens' that allows you to control the flow of execution in order to gain a better understanding of how the program works. -.. image:: https://travis-ci.org/RunestoneInteractive/thinkcspy.svg?branch=master - :target: https://travis-ci.org/RunestoneInteractive/thinkcspy +*Note: RST is deprecated, and the new pretext sources are in the pretext folder, but we will keep the _sources (old RST folder) directory until we are 100% sure that the book has been converted correctly and as thoroughly as possible.* -.. important:: The restructuredText version of this book is deprecated! +## Development Environment +Create and activate a virtual environment and install dependencies: +`python -m venv venv` +`source venv/bin/activate` +`pip install -r requirements.txt` -Building with PreTeXt ---------------------- - -1. Create and activate a virtual environment -2. pip install pretext -3. To build run: pretext build web -4. pretext view - -Note: The pretext sources are in the pretext folder, we will keep the _sources folder until we are 100% sure that the book has been converted correctly and as thoroughly as possible. +Then build the textbook: `pretext build web` +..and finally, run the web server: `pretext view` From a8222db0db9ee2c913cbcd74750c3968804b3665 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:26:02 -0600 Subject: [PATCH 78/90] Update README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 377decf3b..bfdb99803 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,13 @@ This is a fork of the original [thinkcspy](https://github.com/runestoneinteracti ## Development Environment Create and activate a virtual environment and install dependencies: + `python -m venv venv` + `source venv/bin/activate` + `pip install -r requirements.txt` Then build the textbook: `pretext build web` + ..and finally, run the web server: `pretext view` From efd780efa4f9f7df25a7dbec91718e6cc1fb0b18 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:21:56 -0600 Subject: [PATCH 79/90] Fix 12.3 issues --- pretext/IntroRecursion/TheThreeLawsofRecursion.ptx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx b/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx index 0c086c4d3..14c0b1365 100644 --- a/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx +++ b/pretext/IntroRecursion/TheThreeLawsofRecursion.ptx @@ -44,8 +44,11 @@

In the remainder of this chapter we will look at more examples of recursion. In each case we will focus on designing a solution to a problem by using the three laws of recursion.

- - Self Check + +

+ Check your understanding +

+

How many recursive calls are made when computing the sum of the list [2,4,6,8,10]?

@@ -124,5 +127,5 @@
-
+ From 5e4361a992983836cef077d2db5e474994642acb Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:34:56 -0700 Subject: [PATCH 80/90] Fix examples (#6) --- pretext/Iteration/TraversalandtheforLoopByItem.ptx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pretext/Iteration/TraversalandtheforLoopByItem.ptx b/pretext/Iteration/TraversalandtheforLoopByItem.ptx index b46bd2125..4e1cd2f89 100644 --- a/pretext/Iteration/TraversalandtheforLoopByItem.ptx +++ b/pretext/Iteration/TraversalandtheforLoopByItem.ptx @@ -9,23 +9,23 @@

We have previously seen that the for statement can iterate over the items of a sequence (a list of names in the case below).

-for aname in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: - invitation = "Hi " + aname + ". Please come to my party on Saturday!" +for name in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]: + invitation = "Hi " + name + ". Please come to my party on Saturday!" print(invitation)

Recall that the loop variable takes on each value in the sequence of names. The body is performed once for each name. The same was true for the sequence of integers created by the range function.

-for avalue in range(10): - print(avalue) +for value in range(10): + print(value)

Since a string is simply a sequence of characters, the for loop iterates over each character automatically.

-for achar in "Go Spot Go": - print(achar) +for char in "Go Spot Go": + print(char)

The loop variable achar is automatically reassigned each character in the string Go Spot Go. From be3d68fbd8f90f721305684f183a89e50b8d8718 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:36:25 -0700 Subject: [PATCH 81/90] rename ids (#5) --- pretext/Iteration/TraversalandtheforLoopByIndex.ptx | 2 +- pretext/Iteration/TraversalandtheforLoopByItem.ptx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Iteration/TraversalandtheforLoopByIndex.ptx b/pretext/Iteration/TraversalandtheforLoopByIndex.ptx index 6dec6e390..74f053802 100644 --- a/pretext/Iteration/TraversalandtheforLoopByIndex.ptx +++ b/pretext/Iteration/TraversalandtheforLoopByIndex.ptx @@ -1,5 +1,5 @@ -

+
Traversing strings with the <c>for</c> Loop: By Index

It is also possible to use the range function to systematically generate the indices of the characters. The for loop can then be used to iterate over these positions. These positions can be used together with the indexing operator to access the individual diff --git a/pretext/Iteration/TraversalandtheforLoopByItem.ptx b/pretext/Iteration/TraversalandtheforLoopByItem.ptx index 4e1cd2f89..3eed094f8 100644 --- a/pretext/Iteration/TraversalandtheforLoopByItem.ptx +++ b/pretext/Iteration/TraversalandtheforLoopByItem.ptx @@ -1,5 +1,5 @@ -

+
Traversing strings with the <c>for</c> Loop: By Item

A lot of computations involve processing a collection one item at a time. For strings this means that we would like to process one character at a time. From 1d721f01e5d29cb0f6922ba7043947e85c8c9f52 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:37:17 -0700 Subject: [PATCH 82/90] add section on variable agg shorthand (#4) --- pretext/SimplePythonData/UpdatingVariables.ptx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pretext/SimplePythonData/UpdatingVariables.ptx b/pretext/SimplePythonData/UpdatingVariables.ptx index 251d54370..055b81a53 100644 --- a/pretext/SimplePythonData/UpdatingVariables.ptx +++ b/pretext/SimplePythonData/UpdatingVariables.ptx @@ -161,6 +161,24 @@ print(x) + + +

The shorthand x += 1 can be used to signify the same thing as x = x + 1, and other operators such as subtraction and multiplication can do this too.

+ + + + +x = 6 # initialize x +print(x) +x += 1 # update x +print(x) +x *= 2 +print(x) +x -= 4 +print(x) + + +

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

From 9164b2f6fbce3a938ce690ae7c4e7090907ebc98 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:47:25 -0700 Subject: [PATCH 83/90] disable ptx stuff --- .devcontainer.json | 89 +++++++++++++++++++++++++++++ .github/workflows/pretext-cli.yml | 94 +++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 .devcontainer.json create mode 100644 .github/workflows/pretext-cli.yml diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 000000000..922a1238d --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,89 @@ +// (delete the above line to manage this file manually) +////////////////////////////////////////////////////////////// +// +// This file provides configuration options so that a PreTeXt +// project can be edited and built using GitHub's Codespaces. +// It is recommended to keep this in your repository even if you +// do not use this feature, as it will allow other to explore +// your project easily. +// This file will be automatically generated by PreTeXt with the +// latest updates unless you remove the first comment line above. +// +/////////////////////////////////////////////////////////////// + +// commented out because we're not using this but ptx generates it automatically. + +// { +// "name": "PreTeXt-Codespaces", + +// // This Docker image includes some LaTeX support, but is still not to large. Note that if you keep your codespace running, it will use up your GitHub free storage quota. Additional options are listed below. +// "image": "oscarlevin/pretext:small", +// // If you need to generate more complicated assets (such as sageplots) or use additional fonts when building to PDF, comment out the above line and uncomment the following line. +// // "image": "oscarlevin/pretext:full", +// // If you only intend to build for web and don't have any latex-image generated assets, you can use a smaller image: +// // "image": "oscarlevin/pretext:lite", + +// // Add gh cli as a feature (to support codechat) +// "features": { +// "ghcr.io/devcontainers/features/github-cli:1": {} +// }, + +// // Respect the project's designated dependencies +// "postCreateCommand": "pip install -r requirements.txt", + +// // Port forwarding +// // --------------- +// // This is needed by the CodeChat Server. +// "forwardPorts": [ +// // The port used for a Thrift connection between the VSCode CodeChat +// // extension and the CodeChat Server. +// 27376, +// // The port used for an HTTP connection from the CodeChat Client to +// // the CodeChat Server. +// 27377, +// // The port used by a websocket connection between the CodeChat +// // Server and the CodeChat Client. +// 27378 +// ], +// // See the [docs](https://containers.dev/implementors/json_reference/#port-attributes). +// "portsAttributes": { +// "27376": { +// "label": "VSCode extension <-> CodeChat Server", +// "requireLocalPort": true +// }, +// "27377": { +// "label": "CodeChat Client", +// "requireLocalPort": true +// }, +// "27378": { +// "label": "CodeChat Client<->Server websocket", +// "requireLocalPort": true +// // This port needs to be public; however, there's no way to specify port visibility here. See `server.py` in the CodeChat Server for details. +// } +// }, + +// // Configure tool-specific properties. +// "customizations": { +// "codespaces": { +// "openFiles": ["source/main.ptx"] +// }, +// "vscode": { +// "settings": { +// "editor.quickSuggestions": { +// "other": "off" +// }, +// "editor.snippetSuggestions": "top", +// "xml.validation.enabled": false, +// "CodeChat.CodeChatServer.Command": "CodeChat_Server" +// }, +// "extensions": [ +// "ms-vscode.live-server", +// "oscarlevin.pretext-tools", +// "CodeChat.codechat" +// ] +// } +// } + +// // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. +// // "remoteUser": "root" +// } diff --git a/.github/workflows/pretext-cli.yml b/.github/workflows/pretext-cli.yml new file mode 100644 index 000000000..22da9ab94 --- /dev/null +++ b/.github/workflows/pretext-cli.yml @@ -0,0 +1,94 @@ +# (delete the above line to manage this file manually) + +# commented out because we're not using this but ptx generates it automatically. + +# name: PreTeXt-CLI Actions +# on: +# # Runs on pull requests +# pull_request: +# branches: ["*"] +# # Runs on pushes to main +# push: +# branches: ["main"] +# # Runs on demand +# workflow_dispatch: + +# jobs: +# build: +# runs-on: ubuntu-latest +# container: oscarlevin/pretext:full + +# steps: +# - name: Checkout source +# uses: actions/checkout@v4 + +# - name: install deps +# run: pip install -r requirements.txt + +# - name: build deploy targets +# run: pretext build --deploys +# - name: stage deployment +# run: pretext deploy --stage-only + +# - name: Bundle output/stage as artifact +# uses: actions/upload-artifact@v4 +# with: +# name: deploy +# path: output/stage + +# deploy-cloudflare: +# runs-on: ubuntu-latest +# needs: build +# if: vars.CLOUDFLARE_PROJECT_NAME != '' +# permissions: +# contents: read +# deployments: write + +# steps: +# - name: Download artifact +# uses: actions/download-artifact@v4 +# with: +# name: deploy +# path: deploy +# - name: Create 404.html +# run: echo "404 page not found" >> deploy/404.html +# - name: Publish to Cloudflare +# uses: cloudflare/pages-action@v1 +# with: +# apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} +# accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} +# projectName: ${{ vars.CLOUDFLARE_PROJECT_NAME }} +# gitHubToken: ${{ secrets.GITHUB_TOKEN }} +# branch: ${{ github.head_ref || github.ref_name }} +# directory: deploy + +# deploy-ghpages: +# runs-on: ubuntu-latest +# needs: build +# if: vars.PTX_ENABLE_DEPLOY_GHPAGES == 'yes' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) +# permissions: +# contents: read +# pages: write +# id-token: write +# concurrency: +# group: "page" +# cancel-in-progress: false +# environment: +# name: github-pages +# url: ${{ steps.deployment.outputs.page_url }} +# steps: +# - name: Download website artifact +# uses: actions/download-artifact@v4 +# with: +# name: deploy +# path: deploy +# - name: Setup GitHub Pages +# id: check +# uses: actions/configure-pages@v4 +# - name: Upload artifact +# uses: actions/upload-pages-artifact@v3 +# with: +# path: deploy +# - name: Deploy to Github Pages +# id: deployment +# uses: actions/deploy-pages@v4 From 777b2e1bee0d1567299faaacfa053831758a5c6b Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 2 Jan 2025 11:45:03 -0700 Subject: [PATCH 84/90] File fixes (#9) * move with statements to be intro * Fix iterating section * Fix unrelated section issues * use with in examples again * Move old methods from intro * use with open syntax on alt. file reading seciton --- .devcontainer/devcontainer.json | 57 +++++++++++++ README.md | 2 +- .../Files/AlternativeFileReadingMethods.ptx | 22 ++--- pretext/Files/Iteratingoverlinesinafile.ptx | 40 +++++++--- pretext/Files/WithStatements.ptx | 80 ++++++++++++++++--- pretext/Files/WritingTextFiles.ptx | 42 +++++----- pretext/Files/intro-WorkingwithDataFiles.ptx | 49 ------------ pretext/Files/toctree.ptx | 4 +- pretext/Functions/BooleanFunctions.ptx | 9 +-- pretext/Functions/UnitTesting.ptx | 2 - pretext/Selection/Logicaloperators.ptx | 13 ++- 11 files changed, 194 insertions(+), 126 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..efa5f10a4 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,57 @@ +{ + "name": "PreTeXt-Codespaces", + + // This Docker image includes some LaTeX support, but is still not to large. Note that if you keep your codespace running, it will use up your GitHub free storage quota. Additional options are listed below. + "image": "oscarlevin/pretext:small", + // If you need to generate more complicated assets (such as sageplots) or use additional fonts when building to PDF, comment out the above line and uncomment the following line. + // "image": "oscarlevin/pretext:full", + // If you only intend to build for web and don't have any latex-image generated assets, you can use a smaller image: + // "image": "oscarlevin/pretext:lite", + + + + // The following was the previous version of this file, which used the Codespaces base image. It is still available for reference, but is not recommended. + // "image": "mcr.microsoft.com/devcontainers/python:3", + // "features": { + // "ghcr.io/devcontainers/features/node:1": {}, + // "ghcr.io/rocker-org/devcontainer-features/pandoc:1": {} + // }, + // "forwardPorts": [ + // 27377, + // 27378 + // ], + // "portsAttributes": { + // "27378": { + // "label": "CodeChat", + // "onAutoForward": "openPreview", + // "requireLocalPort": true, + // "elevateIfNeeded": true, + // "protocol": "https" + // } + // }, + // "onCreateCommand": "pip install pretext", + // // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "sudo bash ./.devcontainer/postCreateCommand.sh", + + // Configure tool-specific properties. + "customizations": { + "codespaces": { + "openFiles": [ + "source/main.ptx" + ] + }, + "vscode": { + "settings": { + "editor.quickSuggestions": { + "other": "off" + }, + "editor.snippetSuggestions": "top", + "xml.validation.enabled": false + }, + "extensions": ["ms-vscode.live-server", "oscarlevin.pretext-tools"] + } + } + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/README.md b/README.md index bfdb99803..276991c5a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This is a fork of the original [thinkcspy](https://github.com/runestoneinteracti > Programming is not a "spectator sport". It is something you do, something you participate in. It would make sense, then, that the book you use to learn programming should allow you to be active. That is our goal. - > This book is meant to provide you with an interactive experience as you learn to program in Python. You can read the text, watch videos, and write and execute Python code. In addition to simply executing code, there is a unique feature called 'codelens' that allows you to control the flow of execution in order to gain a better understanding of how the program works. +> This book is meant to provide you with an interactive experience as you learn to program in Python. You can read the text, watch videos, and write and execute Python code. In addition to simply executing code, there is a unique feature called 'codelens' that allows you to control the flow of execution in order to gain a better understanding of how the program works. *Note: RST is deprecated, and the new pretext sources are in the pretext folder, but we will keep the _sources (old RST folder) directory until we are 100% sure that the book has been converted correctly and as thoroughly as possible.* diff --git a/pretext/Files/AlternativeFileReadingMethods.ptx b/pretext/Files/AlternativeFileReadingMethods.ptx index 840c794e4..62d1c7908 100644 --- a/pretext/Files/AlternativeFileReadingMethods.ptx +++ b/pretext/Files/AlternativeFileReadingMethods.ptx @@ -20,26 +20,26 @@ of readline this moves the marker to the first character of the next line in the file. In the case of read or readlines the marker is moved to the end of the file.

-
>>> infile = open("ccdata.txt", "r")
->>> aline = infile.readline()
->>> aline
+  
>>> with open("ccdata.txt", "r") as infile:
+>>>  aline = infile.readline()
+>>>  aline
 '1850\-0.37\2.24E-7\n'
 >>>
->>> infile = open("ccdata.txt", "r")
->>> linelist = infile.readlines()
->>> print(len(linelist))
+>>> with open("ccdata.txt", "r") as infile:
+>>>  linelist = infile.readlines()
+>>>  print(len(linelist))
 18
->>> print(linelist[0:4])
+>>>  print(linelist[0:4])
 ['1850\-0.37\2.24E-7\n',
  '1860\-0.34\3.94E-7\n',
  '1870\-0.28\6.6E-7\n',
  '1880\-0.24\1.1\n']
 >>>
->>> infile = open("ccdata.txt", "r")
->>> filestring = infile.read()
->>> print(len(filestring))
+>>> with open("ccdata.txt", "r") as infile:
+>>>  filestring = infile.read()
+>>>  print(len(filestring))
 1282
->>> print(filestring[:256])
+>>>  print(filestring[:256])
 1850  -0.37  2.24E-7
 1860  -0.34  3.94E-7
 1870  -0.28  6.6E-7
diff --git a/pretext/Files/Iteratingoverlinesinafile.ptx b/pretext/Files/Iteratingoverlinesinafile.ptx
index c86a48b21..03d6492b9 100644
--- a/pretext/Files/Iteratingoverlinesinafile.ptx
+++ b/pretext/Files/Iteratingoverlinesinafile.ptx
@@ -1,8 +1,27 @@
 
 
Iterating over lines in a file -

Recall the contents of the ccdata.txt file.

-
+ +

As an example, suppose we have a text file called ccdata.txt that contains + the following data representing statistics about climate change. Although it + would be possible to consider entering this data by hand each time it is used, + you can imagine that it would be time-consuming and error-prone to do this. In + addition, it is likely that there could be data from more sources and + other years. The format of the data file is as follows:

+
Year, Global Average Temperature, Global Emmision of CO2
+ + +

To open this file, we would call the open function. The variable, + fileref, now holds a reference to the file object returned by + open. Again, after the file is closed any further attempts to + use fileref will result in an error.

+
with open("ccdata.txt", "r") as fileref:
+  # do things
+ + + + +

We will now use this file as input in a program that will do some data processing. In the program, we will read each line of the file and print it with some additional text. Because text files are sequences of @@ -46,14 +63,11 @@ construct a simple sentence.

-ccfile = open("ccdata.txt", "r") - -for aline in ccfile: - values = aline.split() - print('In', values[0], 'the average temp. was', values[1], '°C and CO2 emmisions were', values[2], 'gigatons.') - -ccfile.close() - +with open("ccdata.txt", "r") as ccfile: + for aline in ccfile: + values = aline.split() + print('In', values[0], 'the average temp. was', values[1], '°C and CO2 emmisions were', values[2], 'gigatons.') +

You can obtain a line from the keyboard with the input function, and you can process lines of a file. diff --git a/pretext/Files/WithStatements.ptx b/pretext/Files/WithStatements.ptx index a067be262..2519347e1 100644 --- a/pretext/Files/WithStatements.ptx +++ b/pretext/Files/WithStatements.ptx @@ -1,23 +1,79 @@

With Statements -

Now that you have seen and practiced a bit with opening and closing files, there is another mechanism that Python provides for us that cleans up the often forgotten close. Forgetting to close a file does not necessarily cause a runtime error in the kinds of programs you typically write in an introductory CS course. However if you are writing a program that may run for days or weeks at a time that does a lot of file reading and writing you may run into trouble.

-

In version 2.5 Python introduced the concept of a context manager. The context manager automates the process of doing common operations at the start of some task, as well as automating certain operations at the end of some task. In the context of reading and writing a file, the normal operation is to open the file and assign it to a variable. At the end of working with a file the common operation is to make sure that file is closed.

-

The Python with statement makes using context managers easy. The general form of a with statement is:

-
with <create some object that understands context> as <some name>:
-    do some stuff with the object
+  
+  
+  
+  

In order to open files easily in Python, we can use the following form:

+
with <some open statement> as <variable name for the file>:
+    do some stuff with the file
     ...
-

When the program exits the with block, the context manager handles the common stuff that normally happens. For example closing a file. A simple example will clear up all of this abstract discussion of contexts.

+

When the program exits the with block, the file is automatically closed. Consider the following example:

- + -with open('mydata.txt') as md: - print(md) - for line in md: +with open('mydata.txt') as myfile: + print(myfile) + for line in myfile: print(line) -print(md) +print(myfile) -

The first line of the with statement opens the file and assigns it to md then we can iterate over the file in any of the usual ways. and when we are done we simply stop indenting and let Python take care of closing the file and cleaning up.

+

The first line of the with statement opens the file and assigns it to myfile, then we can iterate over each line in the file. When we are done, we simply stop indenting and let Python take care of closing the file and cleaning up.

+ A word of caution: once you read all the lines from a file, it is "spent"; + that is to say, if we tried to read from myfile again in the example above, it would not + work. We would have to open the file again to read again. + +

In this course, you likely will not see the following syntax, but it's still useful to know that it's out there:

+

In Python, we can call the open function to open files before we can use them and the close function to close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

+
+ + + + Method Name + + + Use + + + Explanation + + + + + open + + + open(filename,'r') + + + Open a file called filename and use it for reading. This will return a reference to a file object. + + + + + open + + + open(filename,'w') + + + Open a file called filename and use it for writing. This will also return a reference to a file object. + + + + + close + + + filevariable.close() + + + File use is complete. + + + +
+
diff --git a/pretext/Files/WritingTextFiles.ptx b/pretext/Files/WritingTextFiles.ptx index 94cf90df1..48ba0c089 100644 --- a/pretext/Files/WritingTextFiles.ptx +++ b/pretext/Files/WritingTextFiles.ptx @@ -11,36 +11,30 @@

The program below solves part of the problem. Notice that it reads the data and creates a string consisting of the year of the climate change followed by the global emission. In this example, we simply print the lines as they are created.

-infile = open("ccdata.txt", "r") -aline = infile.readline() -print("Year\tEmmision\n") -while aline: - items = aline.split() - dataline = items[0] + '\t' + items[2] - print(dataline) +with open("ccdata.txt", "r") as infile: aline = infile.readline() - -infile.close() - + print("Year\tEmmision\n") + while aline: + items = aline.split() + dataline = items[0] + '\t' + items[2] + print(dataline) + aline = infile.readline() +

When we run this program, we see the lines of output on the screen. Once we are satisfied that it is creating the appropriate output, the next step is to add the necessary pieces to produce an output file and write the data lines to it. To start, we need to open a new output file by adding another call to the open function, outfile = open("emissiondata.txt",'w'), using the 'w' flag. We can choose any file name we like. If the file does not exist, it will be created. However, if the file does exist, it will be reinitialized as empty and you will lose any previous contents.

Once the file has been created, we just need to call the write method passing the string that we wish to add to the file. In this case, the string is already being printed so we will just change the print into a call to the write method. However, there is one additional part of the data line that we need to include. The newline character needs to be concatenated to the end of the line. The entire line now becomes outfile.write(dataline + '\n'). We also need to close the file when we are done.

The complete program is shown below.

-infile = open("ccdata.txt", "r") -outfile = open("emissiondata.txt", "w") - -aline = infile.readline() -outfile.write("Year \tEmmision\n") -while aline: - items = aline.split() - dataline = items[0] + '\t' + items[2] - outfile.write(dataline + '\n') - aline = infile.readline() - -infile.close() -outfile.close() - +with open("ccdata.txt", "r") as infile: + with open("emissiondata.txt", "w") as outfile: + aline = infile.readline() + outfile.write("Year \tEmmision\n") + while aline: + items = aline.split() + dataline = items[0] + '\t' + items[2] + outfile.write(dataline + '\n') + aline = infile.readline() +
diff --git a/pretext/Files/intro-WorkingwithDataFiles.ptx b/pretext/Files/intro-WorkingwithDataFiles.ptx index 9fa57818f..e43b1797e 100644 --- a/pretext/Files/intro-WorkingwithDataFiles.ptx +++ b/pretext/Files/intro-WorkingwithDataFiles.ptx @@ -4,53 +4,4 @@

So far, the data we have used in this book have all been either coded right into the program, or have been entered by the user. In real life, data reside in files.

For example, web pages, word processing documents, and all data that live in files. In this chapter we will introduce the Python concepts necessary to use data from files in our programs.

For our purposes, we will assume that our data files are text files–that is, files filled with characters. The Python programs that you write are stored as text files. We can create these files in any of a number of ways. For example, we could use a text editor to type in and save the data. We could also download the data from a website and then save it in a file. Regardless of how the file is created, Python will allow us to manipulate the contents.

-

In Python, we must open files before we can use them and close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

- - - - - Method Name - - - Use - - - Explanation - - - - - open - - - open(filename,'r') - - - Open a file called filename and use it for reading. This will return a reference to a file object. - - - - - open - - - open(filename,'w') - - - Open a file called filename and use it for writing. This will also return a reference to a file object. - - - - - close - - - filevariable.close() - - - File use is complete. - - - -
diff --git a/pretext/Files/toctree.ptx b/pretext/Files/toctree.ptx index c701cec7e..152ce4715 100644 --- a/pretext/Files/toctree.ptx +++ b/pretext/Files/toctree.ptx @@ -3,11 +3,11 @@ 4Files 4 4 -4 +4 + 4 4 4 -4 4 diff --git a/pretext/Functions/BooleanFunctions.ptx b/pretext/Functions/BooleanFunctions.ptx index 49e41bacf..54b8f100d 100644 --- a/pretext/Functions/BooleanFunctions.ptx +++ b/pretext/Functions/BooleanFunctions.ptx @@ -1,11 +1,10 @@
Boolean Functions - -

We have already seen that boolean values result from the evaluation of boolean expressions. Since the result of any - expression evaluation can be returned by a function (using the return statement), - functions can return boolean values. This turns out to be a very convenient way to hide the details of complicated tests. For example:

-
+

We have already seen that boolean values result from the evaluation of boolean expressions. Since the result of any + expression evaluation can be returned by a function (using the return statement), + functions can return boolean values. This turns out to be a very convenient way to hide the details of complicated tests. For example:

+ def isDivisible(x, y): diff --git a/pretext/Functions/UnitTesting.ptx b/pretext/Functions/UnitTesting.ptx index 5e0f4a4af..98d29da18 100644 --- a/pretext/Functions/UnitTesting.ptx +++ b/pretext/Functions/UnitTesting.ptx @@ -1,12 +1,10 @@
Unit Testing -

A test case expresses requirements for a program, in a way that can be checked automatically. Specifically, a test asserts something about the state of the program at a particular point in its execution. A unit test is an automatic procedure used to validate that individual units of code are working properly. A function is one form of a unit. A collection of these unit tests is called a test suite.

-

We have previously suggested that it's a good idea to first write down comments about what your code is supposed to do, before actually writing the code. It is an even better idea to write down some test cases before writing a program.

There are several reasons why it's a good habit to write test cases.

diff --git a/pretext/Selection/Logicaloperators.ptx b/pretext/Selection/Logicaloperators.ptx index 2e66a0116..d6906676a 100644 --- a/pretext/Selection/Logicaloperators.ptx +++ b/pretext/Selection/Logicaloperators.ptx @@ -1,13 +1,12 @@
Logical operators - -

There are three logical operators: and, or, and not. The - semantics (meaning) of these operators is similar to their meaning in English. - For example, x > 0 and x < 10 is true only if x is greater than 0 and - at the same time, x is less than 10. How would you describe this in words? You would say that - x is between 0 and 10, not including the endpoints.

-
+

There are three logical operators: and, or, and not. The + semantics (meaning) of these operators is similar to their meaning in English. + For example, x > 0 and x < 10 is true only if x is greater than 0 and + at the same time, x is less than 10. How would you describe this in words? You would say that + x is between 0 and 10, not including the endpoints.

+

n % 2 == 0 or n % 3 == 0 is true if either of the conditions is true, that is, if the number is divisible by 2 or divisible by 3. In this case, one, or the other, or both of the parts has to be true for the result to be true.

From 17318ec242d3ba3e0f3995519f44f1d52bf85978 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:11:30 -0700 Subject: [PATCH 85/90] File fixes (#10) * move with statements to be intro * Fix iterating section * Fix unrelated section issues * use with in examples again * Move old methods from intro * use with open syntax on alt. file reading seciton * fix bugged note --- pretext/Files/WithStatements.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Files/WithStatements.ptx b/pretext/Files/WithStatements.ptx index 2519347e1..4cbf5b1b2 100644 --- a/pretext/Files/WithStatements.ptx +++ b/pretext/Files/WithStatements.ptx @@ -21,9 +21,9 @@ print(myfile)

The first line of the with statement opens the file and assigns it to myfile, then we can iterate over each line in the file. When we are done, we simply stop indenting and let Python take care of closing the file and cleaning up.

- A word of caution: once you read all the lines from a file, it is "spent"; +

A word of caution: once you read all the lines from a file, it is "spent"; that is to say, if we tried to read from myfile again in the example above, it would not - work. We would have to open the file again to read again. + work. We would have to open the file again to read again.

In this course, you likely will not see the following syntax, but it's still useful to know that it's out there:

In Python, we can call the open function to open files before we can use them and the close function to close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

From 69ca69c6f41c443bb2150fa35f12ddc0852796e5 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:19:26 -0700 Subject: [PATCH 86/90] fix note again? --- pretext/Files/WithStatements.ptx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pretext/Files/WithStatements.ptx b/pretext/Files/WithStatements.ptx index 4cbf5b1b2..b45707957 100644 --- a/pretext/Files/WithStatements.ptx +++ b/pretext/Files/WithStatements.ptx @@ -21,9 +21,9 @@ print(myfile)

The first line of the with statement opens the file and assigns it to myfile, then we can iterate over each line in the file. When we are done, we simply stop indenting and let Python take care of closing the file and cleaning up.

-

A word of caution: once you read all the lines from a file, it is "spent"; +

A word of caution: once you read all the lines from a file, it is "spent"; that is to say, if we tried to read from myfile again in the example above, it would not - work. We would have to open the file again to read again.

+ work. We would have to open the file again to read again.

In this course, you likely will not see the following syntax, but it's still useful to know that it's out there:

In Python, we can call the open function to open files before we can use them and the close function to close them when we are done with them. As you might expect, once a file is opened it becomes a Python object just like all other data. shows the functions and methods that can be used to open and close files.

From c8005169e1e71f2b1c9d139e0383df9945c4a389 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:43:26 -0700 Subject: [PATCH 87/90] Fix notes --- pretext/AdditionalTopics/BinaryRepresentations.ptx | 2 ++ pretext/ClassesBasics/UserDefinedClasses.ptx | 2 +- pretext/Iteration/BreakAndContinue.ptx | 4 ++-- pretext/Lists/None.ptx | 4 ++-- pretext/PythonModules/Packages.ptx | 8 ++++---- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/pretext/AdditionalTopics/BinaryRepresentations.ptx b/pretext/AdditionalTopics/BinaryRepresentations.ptx index c17467216..12c83b6c7 100644 --- a/pretext/AdditionalTopics/BinaryRepresentations.ptx +++ b/pretext/AdditionalTopics/BinaryRepresentations.ptx @@ -39,9 +39,11 @@

Our final answer is: 1001110 (base 2)

+

Typically when we write binary, we'll see our bits in groups of 4, because our binary sequences are normally some multiple of 4, like 8, 16, or 32. Because of this, we would add a leading zero and write our previous answer as: 0100 1110 (base 2). +

Converting binary to decimal: As mentioned above, you can simply look at each bit, diff --git a/pretext/ClassesBasics/UserDefinedClasses.ptx b/pretext/ClassesBasics/UserDefinedClasses.ptx index 37bb40c2a..cabf4271a 100644 --- a/pretext/ClassesBasics/UserDefinedClasses.ptx +++ b/pretext/ClassesBasics/UserDefinedClasses.ptx @@ -68,7 +68,7 @@ print("Nothing seems to have happened with the points")

During the initialization of the objects, we created two attributes called x and y for each, and gave them both the value 0.

-

The asignments are not to x and y, but to self.x and self.y. +

The assignments are not to x and y, but to self.x and self.y. The attributes x and y are always attached to a particular instance. The instance is always explicitly referenced with dot notation.

diff --git a/pretext/Iteration/BreakAndContinue.ptx b/pretext/Iteration/BreakAndContinue.ptx index 12913877e..e6068f9d0 100644 --- a/pretext/Iteration/BreakAndContinue.ptx +++ b/pretext/Iteration/BreakAndContinue.ptx @@ -35,6 +35,6 @@ while i < 10: - Notice the difference between the activecode example above for break and this example with continue. - Neither loop prints 5, but in the loop with continue, it continues iterating after where 5 would have been. +

Notice the difference between the activecode example above for break and this example with continue. + Neither loop prints 5, but in the loop with continue, it continues iterating after where 5 would have been.

diff --git a/pretext/Lists/None.ptx b/pretext/Lists/None.ptx index 7d5e6a10d..e706f5265 100644 --- a/pretext/Lists/None.ptx +++ b/pretext/Lists/None.ptx @@ -59,10 +59,10 @@ print(my_list[0])

If you remember nothing else, remember: strings get reassigned, lists don't. This is because strings are immutable; lists are mutable and most of their functions don't return anything (meaning they implicitly return None!).

- You may be wondering how to tell the difference between functions that return something or not. Sometimes +

You may be wondering how to tell the difference between functions that return something or not. Sometimes the name of the method can be a hint (e.g. if it has "set" in the name, it probably won't return, whereas "get" will). If that doesn't help or you're still curious, you should reference the documentation (whether it's official Python - documentation or for a library). No shame in looking it up! + documentation or for a library). No shame in looking it up!

You won't be tested on the information below, but read on for some interesting thoughts on this.

diff --git a/pretext/PythonModules/Packages.ptx b/pretext/PythonModules/Packages.ptx index adf216ce9..0854b2bb1 100644 --- a/pretext/PythonModules/Packages.ptx +++ b/pretext/PythonModules/Packages.ptx @@ -2,8 +2,8 @@
Packages and Dependencies - You won't ever need to deal with dependencies in this course unless you are adding modules to your final project. Nonetheless, using packages - (a package is just a collection of Python modules) is a common practice in Python programming that you should at least be aware of. +

You won't ever need to deal with dependencies in this course unless you are adding modules to your final project. Nonetheless, using packages + (a package is just a collection of Python modules) is a common practice in Python programming that you should at least be aware of.

One key tenant of computer science (or anything, for that matter) is that we don't want to reinvent the wheel if we don't have to. A lot of very smart people have made very useful code, so why not use it?

@@ -38,7 +38,7 @@ numpy==1.26.2

If you're unsure what version of a dependency you have installed, you can run the command: pip show DEPENDENCY, like pip show numpy. Somewhat ironically, there are also packages that can autogenerate a requirements.txt file for you.

- One additional tip worth mentioning is to always specify the bare minimum requirements your code needs to work. +

One additional tip worth mentioning is to always specify the bare minimum requirements your code needs to work. Dependencies normally have dependencies of their own, so we want to minimize the install time and space taken up - when someone is installing your program's requirements. + when someone is installing your program's requirements.

From fa03d49067bc7580c0db2275d2b331bc616f2639 Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:38:19 -0700 Subject: [PATCH 88/90] Fix quote issue --- pretext/Lists/None.ptx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pretext/Lists/None.ptx b/pretext/Lists/None.ptx index e706f5265..29527ba48 100644 --- a/pretext/Lists/None.ptx +++ b/pretext/Lists/None.ptx @@ -73,11 +73,15 @@ print(my_list[0])

Fun (or depressing) fact -- the inventor of null actually regrets his invention:

+

I call it my billion-dollar mistake... At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. +

+

- Tony Hoare +

Despite this, None, null, and nil don't seem to be going anywhere anytime soon. :)

From da12ef38c6454f6151452402c76c609c956e595b Mon Sep 17 00:00:00 2001 From: Ethan Richards <42894274+ezrichards@users.noreply.github.com> Date: Sat, 25 Jan 2025 09:07:43 -0700 Subject: [PATCH 89/90] Fix pseudocode section prompt --- pretext/Selection/Pseudocode.ptx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pretext/Selection/Pseudocode.ptx b/pretext/Selection/Pseudocode.ptx index c5ea43ae0..f8ff51bf6 100644 --- a/pretext/Selection/Pseudocode.ptx +++ b/pretext/Selection/Pseudocode.ptx @@ -22,10 +22,12 @@

Take the following prompt for a problem:

+

Write a program that takes in a fraction in the format NUMERATOR/DENOMINATOR from the user and outputs the quotient and the remainder. If the denominator is 0, print out an error message; if the denominator is anything else, let the user run the program normally. +

We can approach this problem first by writing the following pseudocode:

From 6999dfe4229b392d1ba8a8e52d1145a7cd0f643a Mon Sep 17 00:00:00 2001 From: Jett Morrandez Date: Wed, 16 Apr 2025 16:02:55 -0600 Subject: [PATCH 90/90] All pygame additions --- .../AdditionalTopics/pygame/Introduction.ptx | 105 ++++++++++++++++++ pretext/AdditionalTopics/pygame/image.png | Bin 0 -> 69594 bytes pretext/AdditionalTopics/toctree.ptx | 1 + 3 files changed, 106 insertions(+) create mode 100644 pretext/AdditionalTopics/pygame/Introduction.ptx create mode 100644 pretext/AdditionalTopics/pygame/image.png diff --git a/pretext/AdditionalTopics/pygame/Introduction.ptx b/pretext/AdditionalTopics/pygame/Introduction.ptx new file mode 100644 index 000000000..ebb158449 --- /dev/null +++ b/pretext/AdditionalTopics/pygame/Introduction.ptx @@ -0,0 +1,105 @@ + +
+ Pygame Introduction + +

Another aspect of python that is not specifically covered in this course is Pygame. This section will cover an introduction and key features of pygame so that you could get started programming your own game. + Pygame is a free open-source library for programming games using Python. Pygame is considered a simple library in the world of game development, its capabilities include: graphics and animation, user input handling, + collision detection, event handling, and sprite management. +

+ +

To first use pygame you must install it on your computer. For both Mac and Windows, open vscode and a new terminal (Terminal -> New Terminal). In the terminal type : pip install pygame. If you already have pygame installed + on your computer make sure that it is up to date with the latest version. Once pygame is installed and updated you are ready to get started!

+ +

Key Aspects of Game Development:

+

Game loop: The game loop is a continuous cycle that begins when game play starts and ends based upon certain events happening. The game loop listens for user input such as: a mouse click, key events, the window closing, etc. + based upon these inputs the loop will update the game. This creates the illusion of the user interacting with the game. For example, programming that once a user lost a certain amount of points the game would end, the game + loop would continuously check the amount of points the user had and once it reached a certain threshold the game would quit.

+ +

Event handling: In game development event handling is a way to control responses to an event. When an event occurs such as user input or a collision, the event is directed to an event handler. This is a block of code that runs in + response to the event. For example, if the user collides with an obstacle the game will end.

+ +

Sprites: Sprites are two dimensional animations or objects that often represent characters within the game. In pygame, sprites are typically created as classes and different sprite objects are created from that class. + This could be as the user, as an enemy(ies) etc.

+ +

Collisions: Collisions are an often used concept in game development, many basic games such as car racing, pong, etc. Collision detection is also a type of event handling, where when two objects share the same coordinates + the collision event occurs.

+ +

Game speed: Game speed is an aspect of the game that controls how quickly the game is played. For example, if you are playing an obstacle course, how quickly or not the objects appear is considered the game speed. + Typically this is a variable that can be adjusted by the players depending on the difficulty that they choose to play the game at.

+ + +

When beginning writing any pygame file the first two lines should always be: import pygame and pygame.init(). + These two commands import and initialize the pygame module so that you may use it in your code. You will then want + to create and name the window that your game will appear in outside of your coding environment. To do this:

+ + +window = pygame.display.set_mode((500,500)) #this will create and set the size of your window +pygame.display.set_caption("Name") #this will set the name of your window +exit = False +while !exit: #game loop + for event in pygame.event.get() #listens for events + if event.type == pygame.QUIT: + exit = True + pygame.display.update() + + +

When the above code is run. it should create a blank black window on your computer. All further creative ideas can extend from this central code.

+ +

Drawing in Pygame:

+ + +Color(r,g,b) #Color +pygame.display.set_mode() #Create display window + + +

Pygame can only have a single display active at a time, if set_mode() is called while another window is open, the previous window will be closed. +Using pygame.display.quit() will also shut down the window.

+

pygame.draw.rect- draws a rectangle

+

pygame.draw.polygon- draws a polygon

+

pygame.draw.circle- draws a circle

+

pygame.draw.ellipse- draws an ellipse

+

pygame.draw.arc- draws an elliptical arc

+

pygame.draw.line- draws a straight line

+

pygame.draw.lines- draws multiple contiguous straight line segments

+ +

Events in Pygame:

+

pygame.event.get()-gets events from the queue

+

pygame.event.wait()- waits for single event from the queue

+

pygame.event.clear()- removes all events from the queue

+

To get the state of various input devices, you can forego the event queue and access the input +devices directly with their appropriate modules. For example: pyagme.mouse, pygame.key, pygame.joystick, etc. +If this method is used, pygame requires some from of communication with the system window manager and other parts +of the platform. To keep pygame in sync with the system you will need to call: pygame.event.pump(), to keep everything current. +Usually, this should be called once per game loop.

+ +

The event queue itself contains event objects that can be accessed from the queue by checking for existence or grabbing them +directly off of the stack.

+ +

Mouse Event in Pygame:

+

pygame.mouse.get_pressed()- get the state of the mouse buttons

+

pygame.mouse.get_pos()- get the mouse cursor position

+

pygame.mouse.set_pos()- set the mouse cursor position

+

pygame.mouse.set_visible()- hide or show the mouse cursor

+

pygame.mouse.get_visible()- check if the display is receiving mouse input

+ +

When the display mode is set, the queue will start receiving mouse evets. The mouse buttons themselves will generate: pygameMOUSEBUTTONDOWN/UP events. +Similarly, a pygame.MOUSEMOTION event whenever the mouse is moved. All of these events can be directed to an event handler within the game loop.

+ +

Time in Pygame:

+

pygame.time.get_ticks()- gets the time in milliseconds

+

pygame.time.wait()- pauses the program for a specified amount of time

+

pygame.time.delay()- same^

+

pygame.time.set_timer()- repeatedly create an event on the event queue

+

pygame.time.Clock- creates an object to track the time.

+

Use of time in pygame can add an additional layer of complexity to your game. Whether that is making sure that the user completes a game level within a certain +amount of time, or times the user and records the best time.

+ +

Here is an example of code that moves a box around the screen using the arrow keys.

+
+ + +
+ + + +
diff --git a/pretext/AdditionalTopics/pygame/image.png b/pretext/AdditionalTopics/pygame/image.png new file mode 100644 index 0000000000000000000000000000000000000000..5b67d93fa9fbef5d0962b9364d81a15abfd25cba GIT binary patch literal 69594 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 z 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 literal 0 HcmV?d00001 diff --git a/pretext/AdditionalTopics/toctree.ptx b/pretext/AdditionalTopics/toctree.ptx index 665f794d3..5f1a746a0 100644 --- a/pretext/AdditionalTopics/toctree.ptx +++ b/pretext/AdditionalTopics/toctree.ptx @@ -12,6 +12,7 @@ 4 4 4 +4 4 4