Today: whole-program vs. functions, tuples, dict.items() output pattern, lambda, map, one-liners
>>> t = ('a', 13)
>>> t[0]
'a'
>>> t[1]
13
>>> len(t)
2
>>> t[0] = 'b'
TypeError: 'tuple' object does not support item assignment
Unfortunate syntax shortcut: possible to omit the parenthesis. We will never do this in CS106A code. More readable to spell out in the code that it's a tuple.
>>> t = 1, 4 # This works >>> t (1, 4) >>> t = (4, 5) # Prefer readable/spelled out >>> t (4, 5)
Tuple assignment = shortcut. A way to assign multiple variables in one step.
>>> (x, y) = (3, 4) >>> x 3 >>> y 4
>>> lst = [12, 19, 2, 1] >>> sorted(lst) [1, 2, 12, 19] >>> >>> sorted(lst, reverse=True) [19, 12, 2, 1] >>> >>> lst = ['apple', 'zebra', 'banana'] >>> sorted(lst) ['apple', 'banana', 'zebra']
>>> pairs = [('stanford.edu', '/meh'), ('google.com','/search'),
('stanford.edu', '/admit'), ('google.com', '/aardvark')]
>>> pairs
[('stanford.edu', '/meh'), ('google.com', '/search'), ('stanford.edu', '/admit'), ('google.com', '/aardvark')]
>>> sorted(pairs)
[('google.com', '/aardvark'), ('google.com', '/search'), ('stanford.edu', '/admit'), ('stanford.edu', '/meh')]
Revisit Dict, now that we have tuples
Say we have a dict loaded up with data
>>> d = {'a': 'alpha', 'g': 'gamma', 'b': 'beta'}
The following pattern we've done many times, it works fine. You can still use it.
>>> for key in sorted(d.keys()): ... print(key, d[key]) ... a alpha b beta g gamma
But there is a more direct way to do it.
>>> d = {'a': 'alpha', 'g': 'gamma', 'b': 'beta'}
>>>
>>> d.keys()
dict_keys(['a', 'g', 'b'])
>>> sorted(d.keys())
['a', 'b', 'g']
>>>
>>> d.values()
dict_values(['alpha', 'gamma', 'beta'])
>>>
>>> d.items() # still random order
dict_items([('a', 'alpha'), ('g', 'gamma'), ('b', 'beta')])
>>>
>>> sorted(d.items()) # we'll use this form
[('a', 'alpha'), ('b', 'beta'), ('g', 'gamma')]
>>> for item in sorted(d.items()): ... print(item[0], item[1]) ... a alpha b beta g gamma
d.items() is a list of tuples len-2. Instead of this:
for item in sorted(d.items()):
print(item[0], item[1])
Can write this, much nicer:
for key, value in sorted(d.items()):
print(key, value)
>>> for key, value in sorted(d.items()): ... print(key, value) ... a alpha b beta g gamma
Thought for today: Lambda code is dense. Another way of saying that it is powerful. Sometimes you feel powerful with computer code because the code you write is long. Sometimes you feel even a little more powerful, because the code you write is short!
Consider this def. It has a name + code. What does this give the program? A name associated with some code that can be called, returns a computed value.
def double n:
return n * 2
Within many programs, there are spots where you have a list of xxx and need a list of yyy computed from xxx. The lambda technique here is an amazingly compact way of expressing that part of your program.
e.g. a lambda function that takes in n, returns double its value. Has: 1 param, code, returns double value. Does not have: name, "return", multiple lines
lambda n: n * 2
e.g. a lambda that takes a string and returns its int length * 10.
lambda s: len(s) * 10
Double number lambda:
lambda n: n * 2
>>> nums = [1, 2, 3, 4] >>> map(lambda n: n * 2, nums) <map object at 0x11012c390> >>> list(map(lambda n: n * 2, nums)) [2, 4, 6, 8]
Do these in python3 interpreter >>> They're all 1 line long! (note: abs(n) is absolute value of n)
>>> nums = [1, 2, 3, 4] >>> >>> list(map(lambda n: n * -1, nums)) [-1, -2, -3, -4] >>> >>> list(map(lambda n: 100 - n, nums)) [99, 98, 97, 96] >>> >>> list(map(lambda n: abs(n - 3), nums)) [2, 1, 0, 1] >>>
Solve these with 1 line of code each. Do not call list(), that was just so the examples print in the interpreter.
Have a list of strings. Map a lambda over this list. What is the parameter to the lambda? One string. Whatever the lambda returns, that's what makes up the list of results.
>>> strs = ['Banana', 'apple', 'Zebra', 'coffee', 'Donut'] >>> >>> list(map(lambda s: s.lower(), strs)) ['banana', 'apple', 'zebra', 'coffee', 'donut'] >>> >>> list(map(lambda s: s[0], strs)) ['B', 'a', 'Z', 'c', 'D'] >>>
Demo: first_2x(). Students try the other 2.
The above examples all us lambda to express little functions. Just for completeness, the code of a def can be used instead of a lambda, like this:
>>> nums = [1, 2, 3, 4] >>> def double(n): ... return n * 2 ... >>> list(map(double, nums)) [2, 4, 6, 8]
Where we would put a lambda, just put the name of the function. This is the rare case of referring to a function by name, but not putting () after it. The () calls the function, but here we want to identify the function by name but not call it.
If the code you want is several lines long, expressing it in a def is a better approach. Lambdas are great when the computation needed is short. For multi-line computations, use s a def.