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}}

alt: dict with nested temps dict


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

alt: access d['room1']['t1']


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

alt: use temps var to refer to nested dict


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:
    1. Start with empty dict {}
    2. 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?
    1. d.keys(), or sorted(d.keys())
    2. d.values() - collection of just values (same order as d.keys())
    3. 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
    1. Sorts on tuple[0] first across all tuples
    2. 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 of dict.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.

alt: name double points to black box of
code


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]

alt: map double across list


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:
    1. The word "lambda"
    2. A single parameter and colon
    3. 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.

alt: lambda defines black box


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]

alt: map lambda over numbers


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)