Slide 1
Today: tuples, dict.items() output pattern, lambda, map, one-liners
Slide 2
Dict Square Bracket Nesting
Say for our building we have a "temps" dict with a key for each room - 'room1', 'room2', etc. The value for each room is a nested dict of the sensors in the at room 't1', 't2, with the value being the temperature.
>>> d = {'room1': {'t1': 100, 't2': 102}}
Slide 3
Q1 - Access 'room1'
Q: What is an expression to access the nested 'room1'
dict?
A: This is what square brackets do, so it's dict[key], or in this
case: d['room1']
Slide 4
Q2 - Access 't1'
in 'room1'
Q: What is an expression to get the temperature of sensor 't1'
in
'room1'
?
A: The square brackets work left-to-right. So the expression
d['room1']
points to the inner, nested dict. You can add another pair
of brackets on the right to access inside the nested dict"
>>> d = {'room1': {'t1': 100, 't2': 102}}
>>>
>>> d['room1'] # access nested
{'t1': 100, 't2': 102}
>>>
>>> d['room1']['t1'] # access ['t1'] inside nested
100
Slide 5
Q3: Average Temperature
Q: Write an expression to compute the average temperature of average temp of t1 and t2 in room1?
Answer:
>>> # As above, this accesses one temp
>>> d['room1']['t1']
100
>>>
>>> # Compute average
>>> (d['room1']['t1'] + d['room1']['t2']) / 2
101.0
Slide 6
Q4: Average Temperature With Var
Can store a reference to the nested dict in a var, then use that. We typically do it this way.
>>> # Get a reference to room1 dict, store in var
>>> temps = d['room1']
>>> (temps['t1'] + temps['t2']) / 2
101.0
>>>
Slide 7
Tuples
For more detail see guide Python Tuples
- Written with parenthesis
e.g.(1, 2, 'a')
e.g.('Alex Smith', 12432255)
- Similar to list:
len(), [ ] work the same - Fixed size, typically small
- Sometimes have different types inside
- Immutable - no change, no append
>>> t = ('a', 13, 42)
>>> t[0]
'a'
>>> t[2]
42
>>> len(t)
3
>>> t[0] = 'b'
TypeError: 'tuple' object does not support item assignment
Slide 8
Tuple Syntax Shortcut
Unfortunate syntax shortcut: possible to omit the parenthesis. We will not do this in CS106A code, but you can write it if you like and it is allowed under PEP8. We will write our code more spelled-out, showing explicitly where have a tuple.
>>> t = 1, 4 # This works
>>> t
(1, 4)
>>> t = (4, 5) # We prefer readable/spelled out
>>> t
(4, 5)
Slide 9
Tuples vs. List
They look so similar, but have some real differences. When do you use a list and when a tuple?
Slide 10
When To Use List?
- List:
- Unbound number of elements, possibly a large number
- Number possibly not known ahead of time
- Want .append() to add more
- Typically elements are all the same type
Same-type is not a requirement of a list, but it's typical - You may not use a list as a key in a dict
Slide 11
When To Use Tuple?
- Tuple:
- Small, fixed number of elements
- Number is known ahead of time
- Elements are usually the same type, but more often than with a list they may not be all the same type
- You may use a tuple as a key in a dict
Slide 12
List vs. Tuple Examples
- Store many urls: list
- Store 3 float x,y,z coordinates all together: tuple
e.g.(4, 5.2, 6.1)
- Store many pixels: list
- Store name str and id number together: tuple
e.g.('sally', 123456)
- Store filename of an mp3 file and its length in seconds together:
tuple
e.g.('happy.mp3', 240)
Slide 13
Tuple Assignment = Shortcut
Tuple assignment = shortcut. A way to assign multiple variables in one step.
>>> (x, y) = (3, 4)
>>> x
3
>>> y
4
- Error if the two are not the same len
- Works with lists too
- A bit obscure, you do not need to use this feature
- But handy sometimes (below)
Revisit Dict, now that we have tuples
Slide 14
Dict Load Up
- Common dict pattern:
- Start with empty dict {}
- Loop through data, add in key/value pairs with
in
- Now dict if filled with key/value data
Slide 15
Dict Output Pattern #1
Say we have a dict loaded up with data
>>> d = {'a': 'alpha', 'g': 'gamma', 'b': 'beta'}
The following pattern we used before. This is a fine, standard pattern to use.
>>> for key in sorted(d.keys()):
... print(key, d[key])
...
a alpha
b beta
g gamma
That said, there are some other ways to do it.
Slide 16
Dict Data Out: keys() values() items()
- How to get data out of dict?
d.keys()
, orsorted(d.keys())
d.values()
- collection of just values (same order asd.keys()
)d.items()
- look at this one today
-
These are all "list-like" collections
The list-like collections work with for-loop and in
But they are not lists, no[]
, no.append()
- Items is collection of key/value pairs (each a tuple len-2)
- In this way, dumping out all the dict data (random order)
sorted(d.items())
- sorts the pairs by key - useful form
>>> 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')])
>>>
Slide 17
Note: Sorting With Tuples
- Sorting of tuples
- Sorts on tuple[0] first across all tuples
- If tuple[0] is the same between two elements
Fall back to sorting on tuple[1] and so on
- Lets us combine multiple data items for sorting
- Say we have len-2 tuples of the form:
('ca', 'palo alto')
- Try sorting these tuples
>>> cities = [('tx', 'houston'), ('ca', 'palo alto'), ('ca', 'san jose'), ('tx', 'austin'), ('ca', 'aardvark')]
>>>
>>> sorted(cities)
[('ca', 'aardvark'), ('ca', 'palo alto'), ('ca', 'san jose'), ('tx', 'austin'), ('tx', 'houston')]
>>>
>>> sorted(cities, reverse=True)
[('tx', 'houston'), ('tx', 'austin'), ('ca', 'san jose'), ('ca', 'palo alto'), ('ca', 'aardvark')]
Slide 18
sorted(d.items())
Recall that d.items()
is a list of len-2 key/value tuples (you can ignore the dict_items
name here and just consider the result a list of tuple pairs):
>>> d.items()
dict_items([('a', 'alpha'), ('g', 'gamma'), ('b', 'beta')])
Since sorting of tuples goes by [0] first, and [0] here is the key, the len-2 tuples are in effect sorted by key:
>>> sorted(d.items())
[('a', 'alpha'), ('b', 'beta'), ('g', 'gamma')]
The keys are all unique, so the sorting never looks at the [1] values.
Slide 19
Dict Output Code #2 Almost
- Output
sorted(dict.items()
instead ofdict.keys()
Get (key, value) len-2 tuples - Items has all the data in one step - nice
- item[0] is key, item[1] is value - ok
- You can use this form, but there's a shortcut below
>>> for item in sorted(d.items()):
... print(item[0], item[1])
...
a alpha
b beta
g gamma
Slide 20
Dict Output Code #2
Recall the shortcut
>>> (a, b) = (6, 7)
>>> a
6
>>> b
7
Can use a similar shortcut inside a for loop. Since we are looping over tuples len-2, can specify two variables, and the loop unpacks each tuple into the variables, here key and value:
>>> for key, value in sorted(d.items()):
... print(key, value)
...
a alpha
b beta
g gamma
- You do not need to use this form, it's just a shortcut
- Each len-2 item is "unpacked" into the key, value variables
- This is just a shortcut
- The only time I use this shortcut is with d.items()
Slide 21
Map/Lambda - Advanced Hacker Features
Map - a short way to transform a list - handy, but not super important
Lambda - an important way to package some code. Today we'll use
map()
to explore how lambda
works
Slide 22
Lambda - Dense and Powerful
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!
Slide 23
One-Liner Code Solutions
There is something satisfying about solving a real problem with 1 line of code. The 1-liner code is so dense, we'll will write it a little more deliberately. See how this works below!
Slide 24
What is a def?
Consider the following "double" def. What does this provide to the rest of the program?
def double n:
return n * 2
The def sets up the name of the function, and associates it with that body of code. Later line can refer to this function by name. The drawing below shows a form of this - the name "double" now points to this black-box of code that anybody can call.
Slide 25
double() - How Many Params? How Many Outputs?
Answer: takes in one parameter value. Returns one value.
>>> # Normally don't def a function in the interpreter.
>>> # But it works for little demos like this.
>>>
>>> def double(n):
... return n * 2
...
>>>
>>> double(10)
20
>>> double(144)
288
Slide 26
1. map(fn, list-like)
- map() takes in:
- 1. Takes in a reference to a function
- 2. Takes in any list-like collection
- Runs that function over the list
- Calling the passed-in function once for each element
- Gathers the outputs into a list-like which is returned
A visual of what map() does
map(double, [1, 2, 3, 4, 5]) -> [2, 4, 6, 8, 10]
Slide 27
Aside: map() Result + list()
- The result that map() returns is not a list exactly and does not display clearly in the interpreter
- Therefore we call it like this in the interpreter
list(map(...))
- Thus making a list of the map() result so it prints out correctly
- This use of list() is not needed generally, we're just doing it here for the printing
Slide 28
map() Examples
>>> # We have a "double" def
>>> def double(n):
... return n * 2
...
>>>
>>> map(double, [1, 2, 3, 4, 5])
<map object at 0x100de9bb0>
# why we need list()
>>>
>>> list(map(double, [1, 2, 3, 4, 5]))
[2, 4, 6, 8, 10]
>>>
>>> list(map(double, [3, -1, 10]))
[6, -2, 20]
>>>
>>> list(map(double, range(20)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38]
>>>
Slide 29
map() Example 2 - exclaim()
Say we have an exclaim(s)
function that takes in a string and returns
it uppercase with an exclamation mark at the end. Use map to run
exclaim() over a list of strings.
>>> def exclaim(s):
... return s.upper() + '!'
...
>>>
>>> list(map(exclaim, ['hi', 'woot', 'donut']))
['HI!', 'WOOT!', 'DONUT!']
>>>
>>> list(map(exclaim, ['meh']))
['MEH!']
Enter the Lambda
Slide 30
Lambda Niche
- In the examples above
- 1. Do the def first, define the name + code we want to use
- 2. Then later in the code, map() refers to that name and maps the code over the list
- If the code is short, it would be nice to do the whole thing in one place
- Read on!
- Dense/Powerful code ahead!
Slide 31
Lambda 1-2-3
- "lambda" is a stripped-down syntax to define computation in 1 line
- lambda has the absolute minimum needed
- Below is a lambda which defines code to double a number
- Syntax:
- The word "lambda"
- A single parameter and colon
- An expression defining the output of the lambda, no "return"
- All of today's lambdas will have 1 parameter
Possible to have different numbers, but 1 is very common - Lambda is great where you want a tiny function
Here is a lambda that takes in a number, returns double that number
lambda n: 2 * n
Slide 32
Lambda Black Box
It's like the lambda just defines the black box code, not bothering with giving it name.
Slide 33
Lambda works with map()
Want to double a bunch of numbers? Instead of a separate def, write the lambda inside the map() like this:
>>> list(map(lambda n: n * 2, [1, 2, 3, 4, 5]))
[2, 4, 6, 8, 10]
Slide 34
How To Write Lambda - 1, 2, 3
Slide 35
1. "lambda"
Write the word "lambda"
Slide 36
2. Param:
- What is the lambda input?
- Give the lambda param a good name, followed by colon
- A an int - "n:"
- A string - "s:"
- A mass in kilograms - "mass:" or "kg:"
- Having a good name helps with the next step
Slide 37
3. Expression
- Write the expression for the output
- Fit on one line, use the param
- No "return"
- If the code is long .. consider using a "def" see below
Slide 38
Lambda Examples in Interpreter
Do these in interpreter >>>. Just hit the up-arrow to change the body of the lambda.
>>> nums = [1, 2, 3, 4]
>>>
>>> # n * 10
>>> list(map(lambda n: n * 10, nums))
[10, 20, 30, 40]
>>>
>>> # n * -1
>>> list(map(lambda n: n * -1, nums))
[-1, -2, -3, -4]
>>>
>>> # 100 - n
>>> list(map(lambda n: 100 - n, nums))
[99, 98, 97, 96]
>>>
>>>
Slide 39
Lambda String Examples
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']
>>>
>>> list(map(lambda s: s.upper() + '!', ['hi', 'ho', 'meh']))
['HI!', 'HO!', 'MEH!']
>>>
Slide 40
Examples / Exercises - Map Lambda
These are true one-liner exercises. We'll do a few of them in class, and you can look at the others in the lambda1 section.
Solve these with a 1-line call to map() for each. Do not call list(), that was needed in the interpreter, but here just map() works.
> lambda1 exercises
For reference, here is the syntax for our "double" example:
map(lambda n: 2 * n, [1, 2, 3, 4, 5])
Do these: squared(), diff21() (int)
Then strings: first2x(), first_up() (str)