diff --git a/_sources/AdvancedAccumulation/filter.rst b/_sources/AdvancedAccumulation/filter.rst index 02b4f02b..c62b5cc5 100644 --- a/_sources/AdvancedAccumulation/filter.rst +++ b/_sources/AdvancedAccumulation/filter.rst @@ -34,11 +34,11 @@ iterate with a for loop. .. activecode:: ac21_3_2 - def keep_odds(nums): - new_list = filter(lambda num: num % 2 == 1, nums) - return new_list + def keep_evens(nums): + new_seq = filter(lambda num: num % 2 == 0, nums) + return list(new_seq) - print(keep_odds([3, 4, 6, 7, 0, 1])) + print(keep_evens([3, 4, 6, 7, 0, 1])) **Check Your Understanding** diff --git a/_sources/AdvancedAccumulation/listcomp.rst b/_sources/AdvancedAccumulation/listcomp.rst index d7f3e347..1f0cbdd4 100644 --- a/_sources/AdvancedAccumulation/listcomp.rst +++ b/_sources/AdvancedAccumulation/listcomp.rst @@ -17,7 +17,7 @@ Python provides an alternative way to do ``map`` and ``filter`` operations, call Many programmers find them easier to understand and write. List comprehensions are concise ways to create lists from other lists. The general syntax is:: - [ for in if ] + [ for in if ] where the if clause is optional. For example, @@ -29,14 +29,14 @@ where the if clause is optional. For example, print(yourlist) -The expression is ``value * 2``. The item variable is ``value`` and the sequence is ``things``. This is an alternative way +The transformer expression is ``value * 2``. The item variable is ``value`` and the sequence is ``things``. This is an alternative way to perform a mapping operation. As with ``map``, each item in the sequence is transformed into an item in the new list. Instead of the iteration happening automatically, however, we have adopted the syntax of the for loop which may make it easier to understand. Just as in a regular for loop, the part of the statement ``for value in things`` says to execute some code once for each item in things. Each time that code is executed, ``value`` is bound to one item from ``things``. The code that is executed -each time is the expression at the beginning, ``value * 2``, rather than a block of code indented underneath the for +each time is the transformer expression, ``value * 2``, rather than a block of code indented underneath the for statement. The other difference from a regular for loop is that each time the expression is evaluated, the resulting value is appended to a list. That happens automatically, without the programmer explicitly initializing an empty list or appending each item. @@ -126,7 +126,7 @@ You can also combine ``map`` and ``filter`` operations by chaining them together :chatcodes: :practice: T - **3.** Write code to assign to the variable ``compri`` all the values of the key name in the dictionary ``tester``. Do this using list comprehension. + **3.** Write code to assign to the variable ``compri`` all the values of the key ``name`` in any of the sub-dictionaries in the dictionary ``tester``. Do this using a list comprehension. ~~~~ tester = {'info': [{"name": "Lauren", 'class standing': 'Junior', 'major': "Information Science"},{'name': 'Ayo', 'class standing': "Bachelor's", 'major': 'Information Science'}, {'name': 'Kathryn', 'class standing': 'Senior', 'major': 'Sociology'}, {'name': 'Nick', 'class standing': 'Junior', 'major': 'Computer Science'}, {'name': 'Gladys', 'class standing': 'Sophomore', 'major': 'History'}, {'name': 'Adam', 'major': 'Violin Performance', 'class standing': 'Senior'}]} diff --git a/_sources/AdvancedAccumulation/map.rst b/_sources/AdvancedAccumulation/map.rst index 411533e7..fe9ad296 100644 --- a/_sources/AdvancedAccumulation/map.rst +++ b/_sources/AdvancedAccumulation/map.rst @@ -59,6 +59,13 @@ makes it more clear what the overall structure of the computation is. ``map`` ta sequence. The function is the mapper that transforms items. It is automatically applied to each item in the sequence. You don't have to initialize an accumulator or iterate with a for loop at all. +.. note:: + + Technically, in a proper Python 3 interpreter, the ``map`` function produces an "iterator", which is like a list but + produces the items as they are needed. Most places in Python where you can use a list (e.g., in a for loop) you can + use an "iterator" as if it was actually a list. So you probably won't ever notice the difference. If you ever really + need a list, you can explicitly turn the output of map into a list: ``list(map(...))``. In the runestone environment, ``map`` actually returns a real list, but to make this code compatible with a full python environment, we always convert it to a list. + As we did when passing a function as a parameter to the ``sorted`` function, we can specify a function to pass to ``map`` either by referring to a function by name, or by providing a lambda expression. @@ -68,12 +75,12 @@ either by referring to a function by name, or by providing a lambda expression. return 3*value def tripleStuff(a_list): - new_list = map(triple, a_list) - return new_list + new_seq = map(triple, a_list) + return list(new_seq) def quadrupleStuff(a_list): - new_list = map(lambda value: 4*value, a_list) - return new_list + new_seq = map(lambda value: 4*value, a_list) + return list(new_seq) things = [2, 5, 9] things3 = tripleStuff(things) @@ -89,17 +96,11 @@ Of course, once we get used to using the ``map`` function, it's no longer necess things = [2, 5, 9] things4 = map((lambda value: 4*value), things) - print(things4) + print(list(things4)) # or all on one line - print(map((lambda value: 5*value), [1, 2, 3])) - -.. note:: + print(list(map((lambda value: 5*value), [1, 2, 3]))) - Technically, in a proper Python 3 interpreter, the ``map`` function produces an "iterator", which is like a list but - produces the items as they are needed. Most places in Python where you can use a list (e.g., in a for loop) you can - use an "iterator" as if it was actually a list. So you probably won't ever notice the difference. If you ever really - need a list, you can explicitly turn the output of map into a list: ``list(map(...))``. **Check Your Understanding** diff --git a/_sources/AdvancedAccumulation/zip.rst b/_sources/AdvancedAccumulation/zip.rst index cb25401f..a2ce6dcb 100644 --- a/_sources/AdvancedAccumulation/zip.rst +++ b/_sources/AdvancedAccumulation/zip.rst @@ -46,7 +46,7 @@ so on. L1 = [3, 4, 5] L2 = [1, 2, 3] - L4 = zip(L1, L2) + L4 = list(zip(L1, L2)) print(L4) Here's what happens when you loop through the tuples. @@ -56,7 +56,7 @@ Here's what happens when you loop through the tuples. L1 = [3, 4, 5] L2 = [1, 2, 3] L3 = [] - L4 = zip(L1, L2) + L4 = list(zip(L1, L2)) for (x1, x2) in L4: L3.append(x1+x2) @@ -69,7 +69,7 @@ Or, simplifying and using a list comprehension: L1 = [3, 4, 5] L2 = [1, 2, 3] - L3 = [x1 + x2 for (x1, x2) in zip(L1, L2)] + L3 = [x1 + x2 for (x1, x2) in list(zip(L1, L2))] print(L3) Or, using ``map`` and not unpacking the tuple (our online environment has trouble with unpacking the tuple in a lambda expression): diff --git a/_sources/Classes/AddingOtherMethodstoourClass.rst b/_sources/Classes/AddingOtherMethodstoourClass.rst index 9184b719..b3521233 100644 --- a/_sources/Classes/AddingOtherMethodstoourClass.rst +++ b/_sources/Classes/AddingOtherMethodstoourClass.rst @@ -84,7 +84,7 @@ have one additional parameter as compared to the invocation. **Check Your Understanding** -1. Create a class called Animal that accepts two numbers as inputs and assigns them respevtively to two instance variables: ``arms`` and ``legs``. Create a class method called ``limbs`` that, when called, returns the total number of limbs the animal has. To the variable name ``spider``, assign an instance of ``Animal`` that has 4 arms and 4 legs. Call the limbs method on the ``spider`` instance and save the result to the variable name ``spidlimbs``. +1. Create a class called Animal that accepts two numbers as inputs and assigns them respevtively to two instance variables: ``arms`` and ``legs``. Create an instance method called ``limbs`` that, when called, returns the total number of limbs the animal has. To the variable name ``spider``, assign an instance of ``Animal`` that has 4 arms and 4 legs. Call the limbs method on the ``spider`` instance and save the result to the variable name ``spidlimbs``. .. activecode:: ac_chp13_classes_01 :tags: Classes/ImprovingourConstructor.rst, Classes/AddingOtherMethodstoourClass.rs diff --git a/_sources/Conditionals/Theinandnotinoperators.rst b/_sources/Conditionals/Theinandnotinoperators.rst index 587e896a..d47cb802 100644 --- a/_sources/Conditionals/Theinandnotinoperators.rst +++ b/_sources/Conditionals/Theinandnotinoperators.rst @@ -42,7 +42,7 @@ The ``not in`` operator returns the logical opposite result of ``in``. We can also use the ``in`` and ``not in`` operators on lists! -..activecode:: ac4_4_4 +.. activecode:: ac4_4_4 print("a" in ["a", "b", "c", "d"]) print(9 in [3, 2, 9, 10, 9.0]) diff --git a/_sources/Conditionals/week3a1.rst b/_sources/Conditionals/week3a1.rst index 292dbce8..2fa162fc 100644 --- a/_sources/Conditionals/week3a1.rst +++ b/_sources/Conditionals/week3a1.rst @@ -95,7 +95,7 @@ Chapter Assessment :autograde: unittest :practice: T - Write code that counts the number of words in ``sentence`` that contain *either* an "a" or an "e". Store the result in the variable ``num_a_or_e``. + Write code that counts the number of words in ``sentence`` that contains at least one of the letters "a" and "e". Store the result in the variable ``num_a_or_e``. Note 1: be sure to not double-count words that contain both an a and an e. diff --git a/_sources/Debugging/BeginningtipsforDebugging.rst b/_sources/Debugging/BeginningtipsforDebugging.rst index f0eca0d1..276f532c 100644 --- a/_sources/Debugging/BeginningtipsforDebugging.rst +++ b/_sources/Debugging/BeginningtipsforDebugging.rst @@ -18,7 +18,7 @@ Debugging a program is a different way of thinking than writing a program. The #. Everyone is a suspect (Except Python)! It's common for beginner programmers to blame Python, but that should be your last resort. Remember that Python has been used to solve CS1 level problems millions of times by millions of other programmers. So, Python is probably not the problem. -#. Check your assumptions. At this point in your career you are still developing your mental model of how Python does its work. Its natural to think that your code is correct, but with debugging you need to make your code the primary suspect. Even ifyou think it is right, you should verify that it really is by liberally using print statements to verify that the values of variables really are what you think they should be. You'll be surprised how often they are not. +#. Check your assumptions. At this point in your career you are still developing your mental model of how Python does its work. Its natural to think that your code is correct, but with debugging you need to make your code the primary suspect. Even if you think it is right, you should verify that it really is by liberally using print statements to verify that the values of variables really are what you think they should be. You'll be surprised how often they are not. #. Find clues. This is the biggest job of the detective and right now there are two important kinds of clues for you to understand. diff --git a/_sources/Debugging/KnowyourerrorMessages.rst b/_sources/Debugging/KnowyourerrorMessages.rst index f84f9611..298f5b64 100644 --- a/_sources/Debugging/KnowyourerrorMessages.rst +++ b/_sources/Debugging/KnowyourerrorMessages.rst @@ -329,7 +329,7 @@ See if you can get this program to run successfully: .. activecode:: ac4_7_5 str_time = input("What time is it now?") - str_wait_time = input("What is the number of nours to wait?") + str_wait_time = input("What is the number of hours to wait?") time = int(str_time) wai_time = int(str_wait_time) diff --git a/_sources/Debugging/RuntimeErrors.rst b/_sources/Debugging/RuntimeErrors.rst index 3053763a..57455a0b 100644 --- a/_sources/Debugging/RuntimeErrors.rst +++ b/_sources/Debugging/RuntimeErrors.rst @@ -40,7 +40,7 @@ chapters, so it might be a while before you encounter one. .. mchoice:: question4_5_2 :answer_a: The programmer. - :answer_b: The compiler / interpreter. + :answer_b: The interpreter. :answer_c: The computer. :answer_d: The teacher / instructor. :correct: b diff --git a/_sources/Debugging/intro-DebuggingGeneral.rst b/_sources/Debugging/intro-DebuggingGeneral.rst index 105ddcb5..d76b1060 100644 --- a/_sources/Debugging/intro-DebuggingGeneral.rst +++ b/_sources/Debugging/intro-DebuggingGeneral.rst @@ -24,7 +24,7 @@ the errors that you will inevitably come across. Before computers became digital, debugging could mean looking for insects impeding the functioning of physical relays as in this somewhat `apocryphal tale `_ about `Admiral Grace Hopper `_, a pioneer of computer programming. -Nowadays, debugging doesn't involve bug guts all over your computer but it can still be just as frustrating. To cope with this frustration, this chapter[f] will present some strategies to help you understand why the program you wrote does not behave as intended. +Nowadays, debugging doesn't involve bug guts all over your computer but it can still be just as frustrating. To cope with this frustration, this chapter will present some strategies to help you understand why the program you wrote does not behave as intended. Learning Goals -------------- diff --git a/_sources/Dictionaries/ChapterAssessment.rst b/_sources/Dictionaries/ChapterAssessment.rst index df848d73..eed17ae0 100644 --- a/_sources/Dictionaries/ChapterAssessment.rst +++ b/_sources/Dictionaries/ChapterAssessment.rst @@ -298,7 +298,7 @@ Assessment - Dictionary Accumulation class myTests(TestCaseGui): def testOne(self): - self.assertEqual(sorted(wrd_d.items()), sorted([('Singing', 1), ('in', 2), ('the', 2), ('rain', 2), ('and', 1), ('playing', 1), ('are', 1), ('two', 1), ('entirely', 1), ('different', 1), ('situations,', 1), ('but', 1), ('both', 1), ('can', 1), ('be', 1), ('good.', 1)]), "Testing that wrd_d has been created correctly.") + self.assertEqual(sorted(wrd_d.items()), sorted([('Singing', 1), ('in', 2), ('the', 2), ('rain', 2), ('and', 1), ('playing', 1), ('are', 1), ('two', 1), ('entirely', 1), ('different', 1), ('situations', 1), ('but', 1), ('both', 1), ('can', 1), ('be', 1), ('good', 1)]), "Testing that wrd_d has been created correctly.") myTests().main() diff --git a/_sources/Iteration/WPKeepingTrackofYourIteratorVariableYourIterable.rst b/_sources/Iteration/WPKeepingTrackofYourIteratorVariableYourIterable.rst index c7fb876c..71a0cb68 100644 --- a/_sources/Iteration/WPKeepingTrackofYourIteratorVariableYourIterable.rst +++ b/_sources/Iteration/WPKeepingTrackofYourIteratorVariableYourIterable.rst @@ -115,11 +115,12 @@ The iterator (loop) variable is the variable which stores a portion of the itera :answer_b: list :answer_c: tuple :answer_d: iterable - :answer_e: error, unable to iterate over the object. - :feedback_a: - :feedback_b: - :feedback_c: - :feedback_d: + :answer_e: error, unable to iterate over the object. + :feedback_a: Correct! The iterable is a string. + :feedback_b: Incorrect, there is no list in the code. + :feedback_c: Incorrect, the iterable is not a tuple. + :feedback_d: Incorrect, that is not the best answer for this problem. + :feedback_e: Incorrect, Python can iterate over this type. :correct: a :practice: T diff --git a/_sources/NestedData/jsonlib.rst b/_sources/NestedData/jsonlib.rst index f6a3a5c4..8115dc2a 100644 --- a/_sources/NestedData/jsonlib.rst +++ b/_sources/NestedData/jsonlib.rst @@ -40,6 +40,7 @@ The other function we will use is ``dumps``. It does the inverse of ``loads``. I .. activecode:: ac17_3_2 :language: python + import json def pretty(obj): return json.dumps(obj, sort_keys=True, indent=2) diff --git a/_sources/Sequences/IndexOperatorWorkingwiththeCharactersofaString.rst b/_sources/Sequences/IndexOperatorWorkingwiththeCharactersofaString.rst index 9bfd42a6..2ed72fb5 100644 --- a/_sources/Sequences/IndexOperatorWorkingwiththeCharactersofaString.rst +++ b/_sources/Sequences/IndexOperatorWorkingwiththeCharactersofaString.rst @@ -66,6 +66,8 @@ the index. Remember that the indices start at 0. Any integer expression can be u as an index and as with strings, negative index values will locate items from the right instead of from the left. +When we say the first, third or nth character of a sequence, we generally mean counting the usual way, starting with 1. The nth character and the character AT INDEX n are different then: The nth character is at index n-1. Make sure you are clear on what you mean! + Try to predict what will be printed out by the following code, and then run it to check your prediction. (Actually, it's a good idea to always do that with the code examples. You will learn much more if you force yourself to make a prediction before you see the output.) diff --git a/_sources/Sequences/TheSliceOperator.rst b/_sources/Sequences/TheSliceOperator.rst index 0bb429f8..7a4bfe6f 100644 --- a/_sources/Sequences/TheSliceOperator.rst +++ b/_sources/Sequences/TheSliceOperator.rst @@ -29,10 +29,10 @@ selecting a character: 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. +The ``slice`` operator ``[n:m]`` returns the part of the string starting +with the character at index n and +go up to but *not including* the character at index m. +Or with normal counting from 1, this is the (n+1)st character up to and including the mth character. 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