Download Lambda Filter and Reduce - CS111

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Higher Order Functions: Review
Anonymous Functions
Filter and Reduce
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))
CS111 Computer Programming
In[26]: mapPrefixes('program')
Out[26]:
[‘’,'p','pr','pro','prog','progr','progra','program']
Department of Computer Science
Wellesley College
22-2
Using the local function definition
Which begs the question…
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  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?
o 
3-3
3-4
1
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 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'.
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."
Note that you do not include an explicit return
statement in the body of a lambda function;
return is implicit in lambda.
22-5
Example mapping functions using lambda
22-6
Example mapping functions using lambda
def mapScale(factor, nums):
return map(lambda n: factor*n, nums)
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 [5]: mapScale(3, [8,3,6,7,2,4])
Out[5]: [24,9,18,21,6,12]
In [4]: map(lambda st:st+'s',['donut','muffin','bagel'])
Out[4]: ['donuts','muffins','bagels']
22-7
In [6]: mapScale(10, [8,3,6,7,2,4])
Out[6]: [80,30,60,70,20,40]
22-8
2
Example mapping functions using lambda
Example mapping functions using lambda
words.txt
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
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.
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
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)]
3
Mapping Over Multiple Lists
Using map on Other (non-list) sequences
When mapping over multiple lists, all the lists must have
the same length; if not, an exception will be raised.
The map function can be used on any sequence, but
always returns a list.
def add2(a,b):
return a+b
In [17]: map(lambda s: s.upper(), 'foo')
Out[17]: ['F', 'O', 'O']
In [16]: map(add2, [8,3,5,6], [10,20,30])
In [18]: map(lambda s: s.upper(), ('ant','bat','cat')
Out[18]: ['ANT', 'BAT', 'CAT']
----------------------------------------------------------------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
6,
7,
2,
4])
isEven isEven isEven isEven isEven isEven
True
[8,
False
22-14
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.
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.
3,
In [19]: ''.join(map(lambda s: s.upper(), 'foo'))
Out[19]: 'FOO'
The filter function captures the
filtering pattern
The Filtering Pattern
filterEvens( [8,
For mapping over each letter of a string, we can get a string
from the resulting list of strings by using the join method.
True
6,
False
True
True
2,
4]
21-15
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
4
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']
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]
In[33]: filterSameLength('q',['the','gray','cat','is','big'])
21-17
Out[33]: []
More reduce examples
21-18
Converting base b to decimal
3-19
3-20
5
Exercises
Another pattern: all
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.
o  Python has a built-in all:
o  all(iterable)
In[38]: productList([4,5,2,3])
Out[38]: 120
o  Returns True if all elements are True
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
And another: any
3-22
Remember pset 8?
3-23
3-24
6
In other words:
As compared to original solution:
o  searchmenu should return menu entries such
that all search string terms match any entry
field value
3-25
One more pattern: zip
3-26
More usefully, perhaps…
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
3-28
7
Or even!
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-29
22-30
Python 3 Version
Using map on Other (non-list) sequences
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
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 [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
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
8
Related documents