Skip to content

Commit

Permalink
pip2 week 11
Browse files Browse the repository at this point in the history
  • Loading branch information
presnick committed Nov 9, 2014
1 parent 406e677 commit adc72b7
Show file tree
Hide file tree
Showing 12 changed files with 423 additions and 89 deletions.
5 changes: 4 additions & 1 deletion pip2/scripts/session_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ def get_codes(fnames):
sessions[14] = ["Prediction/intro-prediction.rst", "Prediction/hangman_guesser.rst", "Prediction/rule-based.rst", "Prediction/shannon_guesser.rst", "Prediction/training.rst", "Prediction/evaluation.rst"]
sessions[15] = ["PythonModules/intro-ModulesandGettingHelp.rst", "PythonModules/Therandommodule.rst", "PythonModules/Glossary.rst", "PythonModules/Exercises.rst"]
sessions[16] = ["StringFormatting/intro-PrintinginPython2.7.rst", "StringFormatting/Interpolation.rst", "StringFormatting/CSV.rst", "StringFormatting/Exercises.rst"]

sessions[17] = ["RESTAPIs/intro.rst", "RESTAPIs/RequestURLs.rst", "RESTAPIs/jsonlib.rst", "RESTAPIs/unicode.rst", "RESTAPIs/flickr.rst"]
sessions[18] = ["Classes/intro-ClassesandObjectstheBasics.rst", "Classes/ObjectsRevisited.rst", "Classes/UserDefinedClasses.rst", "Classes/ImprovingourConstructor.rst", "Classes/AddingOtherMethodstoourClass.rst", "Classes/ObjectsasArgumentsandParameters.rst", "Classes/ConvertinganObjecttoaString.rst", "Classes/InstancesasReturnValues.rst", "Classes/sorting_instances.rst", "Classes/Glossary.rst", "Classes/Exercises.rst"]
sessions[19] = ["Assignments/session21.rst"]
sessions[20] = []
f = open('session_codes.txt', 'w')
g = open('json_sessin_codes.txt', 'w')

Expand Down
161 changes: 161 additions & 0 deletions pip2/source/AdvancedAccumulation/exercises.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
.. Copyright (C) Paul Resnick. 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".
Exercises
---------


Write equivalent code using map instead of the manual accumulation below

.. activecode:: map_exercise_1

things = [3, 5, -4, 7]

accum = []
for thing in things:
accum.append(thing+1)
print accum

Use manual accumulation to define the lengths function below.

.. activecode:: map_exercise_2

def lengths(strings):
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths
of strings in the input list. Use manual accumulation!"""
# fill in this function's definition to make the test pass.

import test
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3])


Now define lengths using map instead.

.. activecode:: map_exercise_3

def lengths(strings):
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths
of strings in the input list. Use map!"""
# fill in this function's definition to make the test pass.

import test
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3])

Now define lengths using a list comprehension instead.

.. activecode:: listcomp_exercise_1

def lengths(strings):
"""lengths takes a list of strings as input and returns a list of numbers that are the lengths
of strings in the input list. Use a list comprehension!"""
# fill in this function's definition to make the test pass.

import test
test.testEqual(lengths(["Hello", "hi", "bye"]), [5, 2, 3])


.. activecode:: filter_1

things = [3, 5, -4, 7]
# write code to produce a list of only the positive things, [3, 5, 7], via manual accumulation

.. activecode:: filter_2

things = [3, 5, -4, 7]
# write code to produce a list of only the positive things, [3, 5, 7], via manual accumulation

# define longwords using manual accumulation

.. activecode:: filter_3

def longwords(strings):
"""Return a shorter list of strings containing only the strings with more than four characters. Use manual accumulation."""
# write your code here

import test
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"])

# define longwords using filter

.. activecode:: filter_4

def longwords(strings):
"""Return a shorter list of strings containing only the strings with more than four characters. Use the filter function."""
# write your code here

import test
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"])

# define longwords using a list comprehension

.. activecode:: listcomp_exercise_2

def longwords(strings):
"""Return a shorter list of strings containing only the strings with more than four characters. Use a list comprehension."""
# write your code here

import test
test.testEqual(longwords(["Hello", "hi", "bye", "wonderful"]), ["Hello", "wonderful"])


Now combine lengths with longwords to make a function that returns the lengths of those strings that have at least 4 characters. Try it first with a list comprehension.

.. activecode:: listcomp_exercise_3

def longlengths(strings):
return None

import test
test.testEqual(longlengths(["Hello", "hi", "bye", "wonderful"]), [5, 9])

Now try doing it using map and filter.

.. activecode:: listcomp_exercise_4

def longlengths(strings):
return None

import test
test.testEqual(longlengths(["Hello", "hi", "bye", "wonderful"]), [5, 9])

Write a function that takes a list of numbers and returns the sum of the squares of all the numbers. First try it using an accumulator pattern.

.. activecode:: reduce_exercise_2

def sumSquares(L):
return None

nums = [3, 2, 2, -1, 1]

import test
test.testEqual(sumSquares(nums), 19)

Now, try it using map and sum

.. activecode:: reduce_exercise_3

def sumSquares(L):
return None

nums = [3, 2, 2, -1, 1]

import test
test.testEqual(sumSquares(nums), 19)


Finally, try doing it using reduce

.. activecode:: reduce_exercise_3

def sumSquares(L):
return None

nums = [3, 2, 2, -1, 1]

import test
test.testEqual(sumSquares(nums), 19)
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.. Copyright (C) Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris
Meyers, and Dario Mitchell. Permission is granted to copy, distribute
.. Copyright (C) Paul Resnick. 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
Expand Down Expand Up @@ -33,4 +32,6 @@ Again, this pattern of computation is so common that python offers a more compac

print keep_odds([3, 4, 6, 7, 0, 1])

Now try the filter exercises in session22.py
Exercises
---------

20 changes: 20 additions & 0 deletions pip2/source/AdvancedAccumulation/intro.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. Copyright (C) Paul Resnick. 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".
.. _list_comp_chap:

Introduction: Map, Filter, Reduce and List Comprehensions
=========================================================

Let's revisit the :ref:`accumulator pattern <accum_pattern>`. We have frequently taken a list and produced another list from it that contains either a subset of the items or a transformed version of each item. When each item is transformed we say that the operation is a **mapping, or just a map** of the original list. When some items are omitted, we call it a **filter**.

Python provides built-in functions ``map`` and ``filter``. Python also provides a new syntax, called **list comprehensions**, that lets you express a mapping and/or filtering operation. Just as with named functions and lambda expressions, some students seem to find it easier to think in terms of the map and filter functions, while other students find it easier to read and write list comprehensions. You'll learn both ways; one may even help you understand the other. Most python programmers use list comprehensions, so make sure you learn to read those. In this course, you can choose to learn to write list comprehensions or to use map and filter, whichever you prefer. You should learn to read both list comprehensions and map/filter.

Other common accumulator patterns on lists ``reduce`` or aggregate all the values into a single value.

Map, filter, and reduce are commands that you would use in high-performance computing on big datasets. See `MapReduce on Wikipedia <http://en.wikipedia.org/wiki/MapReduce>`_.
73 changes: 73 additions & 0 deletions pip2/source/AdvancedAccumulation/listcomp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.. Copyright (C) Paul Resnick Brad. 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".
List Comprehensions
-------------------

Python provides an alternative way to do map and filter operations, called a **list comprehension**. Many programmers find them easier to understand and write. List comprehensions are concise ways to create lists from other lists. The general syntax is::

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

where the if clause is optional. For example,

.. activecode:: listcomp_7

things = [2, 5, 9]

yourlist = [value * 2 for value in things]

print yourlist

The 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 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.

The ``if`` clause of a list comprehension can be used to do a filter operation. To perform a pure filter operation, the expression can be simply the variable that is bound to each item. For example, the following list comprehension will keep only the positive numbers from the original list.

.. activecode:: listcomp_8

def keep_evens(nums):
new_list = [num for num in nums if num % 2 == 0]
return new_list

print keep_evens([3, 4, 6, 7, 0, 1])

You can also combine map and filter operations by chaining them together, or with a single list comprehension.

.. activecode:: listcomp_9

things = [3, 4, 6, 7, 0, 1
#chaining together filter and map:
# first, filter to keep only the even numbers
# double each of them
print map(lambda x: x*2, filter(lambda y: y % 2 == 0, things))

# equivalent version using list comprehension
print [x*2 for x in things if x % 2 == 0]


**Check your understanding**

.. mchoicemf:: test_question9_20_1
:answer_a: [4,2,8,6,5]
:answer_b: [8,4,16,12,10]
:answer_c: 10
:answer_d: [10].
:correct: d
:feedback_a: Items from alist are doubled before being placed in blist.
:feedback_b: Not all the items in alist are to be included in blist. Look at the if clause.
:feedback_c: The result needs to be a list.
:feedback_d: Yes, 5 is the only odd number in alist. It is doubled before being placed in blist.

What is printed by the following statements?

.. code-block:: python
alist = [4,2,8,6,5]
blist = [num*2 for num in alist if num%2==1]
print blist
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
.. Copyright (C) Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris
Meyers, and Dario Mitchell. Permission is granted to copy, distribute
.. Copyright (C) Paul Resnick. 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".
Introduction: Map, Filter, and List Comprehensions
==================================================

Let's revisit the :ref:`accumulator pattern <accum_pattern>`. We have frequently taken a list and produced another list from it that contains either a subset of the items or a transformed version of each item. When each item is transformed we say that the operation is a **mapping, or just a map** of the original list. When some items are omitted, we call it a **filter**.

Python provides built-in functions ``map`` and ``filter``. Python also provides a new syntax, called **list comprehensions**, that lets you express a mapping and/or filtering operation. Just as with named functions and lambda expressions, some students seem to find it easier to think in terms of the map and filter functions, while other students find it easier to read and write list comprehensions. You'll learn both ways; one may even help you understand the other. Most python programmers use list comprehensions, so make sure you learn to read those; you can choose to learn to write list comprehensions or to use map and filter, whichever you prefer.
Map
---
Expand All @@ -34,7 +27,7 @@ The following function produces a new list with each item in the original list d
things = doubleStuff(things)
print things

The doubleStuff function is an example of the accumulator pattern. On line 3, new_list is initialized. On line 5, the doubled value for the current item is produced and on line 6 it is appended to the list we're accumulating. Line 7 executes after we've process all the items in the original list: it returns the new_list. Once again, codelens helps us to see the actual references and objects as they are passed and returned.
The doubleStuff function is an example of the accumulator pattern, in particular the mapping pattern. On line 3, new_list is initialized. On line 5, the doubled value for the current item is produced and on line 6 it is appended to the list we're accumulating. Line 7 executes after we've processrf all the items in the original list: it returns the new_list. Once again, codelens helps us to see the actual references and objects as they are passed and returned.

.. codelens:: listcomp_2

Expand Down Expand Up @@ -78,13 +71,9 @@ Of course, once we get used to using the map function, it's no longer necessary

things = [2, 5, 9]

things4 = map(lambda value: 4*value, things)
things4 = map((lambda value: 4*value), things)
print things4

# or all on one line
print map(lambda value: 5*value, [1, 2, 3])

.. note::

There are some problems with the implementation of the map function in this online environment. So take a look at the exercises in the file session22.py
print map((lambda value: 5*value), [1, 2, 3])

Loading

0 comments on commit adc72b7

Please sign in to comment.