Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Anonymous Functions
Filter and Reduce
CS111 Computer Programming
Department of Computer Science
Wellesley College
Higher Order Functions: Review
Functions that take other functions as parameters
or return them as results are called higher-order
functions.
def mapPrefixes(string):
# Can't define this outside of mapPrefixes, because
# it needs to refer to parameter named "string"
def prefix(i):
return string[:i]
return map(prefix, range(len(string)+1))
In[26]: mapPrefixes('program')
Out[26]:
[‘’,'p','pr','pro','prog','progr','progra','program']
22-2
Using the local function definition
o Achieves two important goals
o 1) The scoping rules of Python enable the inner function
that is defined inside the outer function to access the
local variables and parameters of the outer function.
o Prefix can access string…
2) We do not “pollute” the module’s name space. The
name prefix is bound only inside the body of
mapPrefixes.
def mapPrefixes(string):
# Can't define this outside of mapPrefixes, because
# it needs to refer to parameter named "string"
def prefix(i):
return string[:i]
return map(prefix, range(len(string)+1))
o
3-3
Which begs the question…
o Why do we need to name those inner functions?
o Nobody outside the body of the outer function can use
or access those names
o Can we make and use functions without ever naming
them?
3-4
lambda notation creates anonymous functions
Sometimes it is inconvenient to define a named
function just in order to pass it as the functional
argument to map. Python provides the alternative of
using so-called lambda notation to create an
anonymous function. For example, the notation
lambda n: n*2
creates an anonymous function that takes a single
parameter named n and returns the value n*2. You
can pronounce this as "I am a function that takes a
parameter n and returns n*2."
22-5
lambda notation creates anonymous functions
lambda st: st+'s'
creates an anonymous function that takes a single
parameter named st and returns the value st+'s'.
Note that you do not include an explicit return
statement in the body of a lambda function;
return is implicit in lambda.
22-6
Example mapping functions using lambda
In [2]: map(lambda n:n*2, [8,3,6,7,2,4])
Out[2]: [16, 6, 12, 14, 4, 8]
In [3]: map(lambda n:n*n, [8,3,6,7,2,4])
Out[3]: [64, 9, 36, 49, 4, 16]
In [4]: map(lambda st:st+'s',['donut','muffin','bagel'])
Out[4]: ['donuts','muffins','bagels']
22-7
Example mapping functions using lambda
def mapScale(factor, nums):
return map(lambda n: factor*n, nums)
In [5]: mapScale(3, [8,3,6,7,2,4])
Out[5]: [24,9,18,21,6,12]
In [6]: mapScale(10, [8,3,6,7,2,4])
Out[6]: [80,30,60,70,20,40]
22-8
Example mapping functions using lambda
def mapPrefixes(string):
return map(lambda i: string[:i+1], range(len(string)))
In [7]: mapPrefixes('cat')
Out[7]: ['c','ca','cat']
In [8]: mapPrefixes('program')
Out[8]: ['p','pr','pro','prog','progr','progra','program']
22-9
Example mapping functions using lambda
words.txt
ant
bat
cat
In [9]: open('words.txt').readlines()
Out[9]: ['ant\n','bat\n','cat\n']
def linesFromFile(filename):
f = open(filename, 'r')
lines = map(lambda line:line.strip(), f.readlines())
f.close()
return lines
In [10]: linesFromFile('words.txt')
Out[10]: ['ant','bat','cat']
22-10
mapPreConcat
Recall, the mapPreConcat function takes a string
pre and a list of strings and returns the result of
concatenating pre in front of every string in the list.
def mapPreConcat(pre,strings):
def concat(i):
return pre+strings[i]
return map(concat,range(len(strings)))
In [11]: mapPreConcat('com', ['puter','pile','mute'])
Out[11]: ['computer','compile','commute']
Redefine the mapPreConcat function from above so
that it uses lambda notation rather than a locally
22-11
defined function.
Mapping Over Multiple Lists
The map function allows any number of list arguments
as long as the supplied function takes a number of
arguments that's the same as the number of lists.
def add2(a,b):
return a+b
In [12]: map(add2, [8,3,5], [10,20,30])
Out[12]: [18, 23, 35]
In [13]: map(lambda a,b: a+b, [8,3,5], [10,20,30])
Out[13]: [18, 23, 35]
In [14]: map(lambda a,b: a*b, [8,3,5], [10,20,30])
Out[14]: [80, 60, 150]
In [15]: map(lambda a,b: (a,b), [8,3,5], [10,20,30])
22-12
Out[15]: [(8,10), (3,20), (5,30)]
Mapping Over Multiple Lists
When mapping over multiple lists, all the lists must have
the same length; if not, an exception will be raised.
def add2(a,b):
return a+b
In [16]: map(add2, [8,3,5,6], [10,20,30])
----------------------------------------------------------------TypeError
Traceback (most recent call
last)
<ipython-input-93-e73284726> in <module>()
----> 1 map(add2, [8,3,5,6], [10,20,30])
TypeError: unsupported operand type(s) for +: 'int' and
'NoneType'
22-13
Using map on Other (non-list) sequences
The map function can be used on any sequence, but
always returns a list.
In [17]: map(lambda s: s.upper(), 'foo')
Out[17]: ['F', 'O', 'O']
In [18]: map(lambda s: s.upper(), ('ant','bat','cat')
Out[18]: ['ANT', 'BAT', 'CAT']
For mapping over each letter of a string, we can get a string
from the resulting list of strings by using the join method.
In [19]: ''.join(map(lambda s: s.upper(), 'foo'))
Out[19]: 'FOO'
22-14
The Filtering Pattern
We've seen examples of the filtering pattern, in which
an output list includes only those input elements for
which a certain predicate is True.
filterEvens( [8,
3,
6,
7,
2,
4])
isEven isEven isEven isEven isEven isEven
True
[8,
False
True
6,
False
True
True
2,
4]
21-15
The filter function captures the
filtering pattern
The Python filter function captures this pattern. It
takes a predicate function and a list and returns a list of
all items for which the predicate function returns True.
def isEven(n):
return n%2==0
In[28]: filter(isEven, [8,3,6,7,2,4])
Out[28]: [8, 6, 2, 4]
def filterEven(nums):
return filter(isEven, nums)
In [29]: filterEven([8,3,6,7,2,4])
Out[29]: [8, 6, 2, 4]
21-16
Exercises
Using the filter function, define a filterPositive
function that takes a list of numbers and returns a list of
its positive elements.
In[30]: filterPositives([8,-3,6,7,-2,-4,5])
Out[30]: [8, 6, 7, 5]
Using the filter function, define a filterSameLength
function that takes a string st and a list of strings and
returns all the strings in the list that have the same
length as st.
In[31]: filterSameLength('ant',['the','gray','cat','is','big'])
Out[25]: ['the','cat','big']
In[32]: filterSameLength('purr',['the','gray','cat','is','big'])
Out[26]: ['gray']
In[33]: filterSameLength('q',['the','gray','cat','is','big'])
21-17
Out[33]: []
The reduce function captures the
accumulation pattern
Python supplies a reduce function that can be used to
accumulate the elements of a list into a result that may
not be a list.
In[34]: def plus(a,b): return a+b
In[35]: reduce(plus, [8,12,5,7,6,4], 0)
Out[35]: 42
In[36]: reduce(plus, ['I','have','a','dream'], '')
Out[36]: 'Ihaveadream'
In[37]: reduce(plus, [[8,2,5],[17],[],[6,3]], [])
Out[37]: [8,2,5,17,6,3]
21-18
More reduce examples
3-19
Converting base b to decimal
3-20
Exercises
Using the reduce function, define a productList
function that takes a list of numbers and returns the
product of all the elements in the list.
In[38]: productList([4,5,2,3])
Out[38]: 120
Using the reduce function, define an areAllPositive
function that takes a list of numbers and returns True if
all the elements are positive. Otherwise the function
returns False.
In[39]: areAllPositive([4,5,2,3])
Out[39]: True
In[40]: areAllPositive([4,5,-2,3])
Out[40]: False
In[41]: areAllPositive([-4,5,2,-3])
Out[41]: False
21-21
Another pattern: all
o Python has a built-in all:
o all(iterable)
o Returns True if all elements are True
3-22
And another: any
3-23
Remember pset 8?
3-24
In other words:
o searchmenu should return menu entries such
that all search string terms match any entry
field value
3-25
As compared to original solution:
3-26
One more pattern: zip
o Useful in data analysis
o zip takes several iterables I1, I2, …
o And returns a list of tuples
o Where the k’th tuple is made up ot the k’th members of
I1, I2,…
3-27
More usefully, perhaps…
3-28
Or even!
22-29
Python 3 WARNING
o This is the first major departure from our
attempts to make this course independent of
python version.
o So far the differences between python 2 and
python 3 have not been great:
o
o
import tkinter as tk NOT import Tkinter as tk
print(astring) NOT print astring
o Now we have a ***big*** difference
o In python 3, map returns an iterator, not a list.
22-30
Using map on Other (non-list) sequences
The map function can be used on any sequence, but
always returns a list.
NOT true in Python 3
In [17]: map(lambda s: s.upper(), 'foo')
Out[17]: ['F', 'O', 'O']
In [18]: map(lambda s: s.upper(), ('ant','bat','cat')
Out[18]: ['ANT', 'BAT', 'CAT']
For mapping over each letter of a string, we can get a string
from the resulting list of strings by using the join method.
In [19]: ''.join(map(lambda s: s.upper(), 'foo'))
Out[19]: 'FOO'
22-31
Python 3 Version
Using map on Other (non-list) sequences
The map function can be used on any sequence, but
always returns n iterator.
In [17]: map(lambda s: s.upper(), 'foo')
Out[17]: <map object at 0x10206e588>
In [18]: map(lambda s: s.upper(), ('ant','bat','cat')
Out[18]: <map object at 0x10210a9b0>
In [19]: for i in map(lambda x: x+x, [1,2,3]):
print(i)
2
4
6
For mapping over each letter of a string, we can get a string
from the resulting list of strings by using the join method.
In [20]: ''.join(map(lambda s: s.upper(), 'foo'))
Out[20]: 'FOO'
22-32