Skip to content
Snippets Groups Projects
Commit 3e48aebb authored by LOUIS TYRRELL OLIPHANT's avatar LOUIS TYRRELL OLIPHANT
Browse files

started lec 23 function references

parent 5c142ed8
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
## Warmup
%% Cell type:code id: tags:
``` python
# Warmup 1: Complete the recursive function.
# Write a function that prints nested lists with indenting
#
fav_stuff = [ "road bike",
["PB&J", "brownies", "spaghetti", "apples"] ,
("Brooks Ghost 13", "hoodie", "gloves"),
"macbook air",
[ "Johndee.com", "https://www.weather.gov/mkx/"],
["A", "K", ("S", "D", "K")]
]
def print_with_indenting(directory, indent_level):
for subitem in directory:
if type(subitem) == list or type(subitem) == tuple:
print("\t" * indent_level + str(type(subitem)))
# TODO make recursive call
else:
print("\t" * indent_level + str(subitem))
print_with_indenting(fav_stuff, 0)
```
%% Cell type:markdown id: tags:
[PythonTutor Link](https://pythontutor.com/visualize.html#code=def%20mystery%28a,%20b%29%3A%20%0A%23%20precondition%3A%20assume%20a%20%3E%200%20and%20b%20%3E%200%0A%20%20%20%20if%20b%20%3D%3D%201%3A%20%0A%20%20%20%20%20%20%20%20return%20a%3B%0A%20%20%20%20return%20a%20*%20mystery%28%20a,%20b%20-%201%20%29%0A%0A%23%20make%20a%20function%20call%20here%0Amystery%287,%205%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false)
%% Cell type:code id: tags:
``` python
# Warmup 2: Trace Recursion by hand .... possible exam question
def mystery(a, b):
# precondition: assume a > 0 and b > 0
if b == 1:
return a;
return a * mystery( a, b - 1 )
# make a function call here
mystery(7, 5)
#Q: What would be the result if we call
#. mystery(-3, -1) ??
```
%% Output
16807
%% Cell type:markdown id: tags:
# Functions are Objects!
## Reading
- [Python for Everybody, 10.8](https://runestone.academy/ns/books/published/py4e-int/dictionaries/toctree.html)
As we have learned previously, all variables in Python refer to objects.
This is also true for functions -- their name refers to a function object, and it gives us more power as programmers.
## Learning Objectives
- Define a function reference and trace code that uses function references.
- Explain the default use of sorted() on lists of tuples, and dictionaries.
- Sort a list of tuples, a list of dictionaries, or a dictionary using a function as a key.
- Use a lambda expression when sorting.
%% Cell type:markdown id: tags:
## Function Names Refer To Function Objects
Just like variables, function names refer to objects -- specifically function objects. This means that you can treat the name of a function the same way you treat other variables. For example, you could call `type()` on a function name.
%% Cell type:code id: tags:
``` python
def blah():
pass
type(blah)
```
%% Output
function
%% Cell type:markdown id: tags:
Just like you can have two variables refer to the same list, you could assign a variable to hold the save reference as a function name. Check it out in [PythonTutor](https://pythontutor.com/render.html#code=x%20%3D%20%5B1,2,3%5D%0Ay%20%3D%20x%0A%0Adef%20f%28some_list%29%3A%20%20%20%23%20what%20is%20f%3F%20%0A%20%20%20%20return%20some_list%5B-1%5D%0A%0Az%20%3D%20f%28y%29%20%20%23%20z%20stores%20the%20result%20of%20a%20call%20to%20f%0A%0Ag%20%3D%20f%20%20%23%20what%20is%20g%3F&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false).
%% Cell type:code id: tags:
``` python
# function references
# try this in Python Tutor
x = [1,2,3]
y = x
def f(some_list): # what is f?
return some_list[-1]
z = f(y) # z stores the result of a call to f
g = f # what is g?
# TODO: Try calling the function using the variable g
```
%% Cell type:markdown id: tags:
### Define a function reference and trace code that uses function references.
%% Cell type:markdown id: tags:
![function%20reference.png](attachment:function%20reference.png)
%% Cell type:markdown id: tags:
## Functions can be passed as arguments!
Take a look at the code below. Watch it run using [PythonTutor](https://pythontutor.com/render.html#code=def%20hammer%28%29%3A%0A%20%20%20%20print%28%22tap%20tap%20tap%22%29%0A%0Adef%20call_n_times%28f,%20n%29%3A%0A%20%20%20%20for%20i%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20f%28%29%0A%0Acall_n_times%28hammer,%203%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false). Then modify the code to finish the `screwdriver()` function and write a line of code to call `call_n_times()` passing in as arguments your `screwdriver` function and the value 5.
%% Cell type:code id: tags:
``` python
# function references can be passed as arguments ...Wow!
# first: try this in Python Tutor
def hammer():
print("tap tap tap")
# then on your own: define a function called screwdriver
def screwdriver():
pass
def call_n_times(f, n):
for i in range(n):
f()
call_n_times(hammer, 3)
# then on your own: invoke call_n_times with screwdriver and 5 as arguments
```
%% Output
tap tap tap
tap tap tap
tap tap tap
%% Cell type:markdown id: tags:
## Your turn!
Calculate the distance between two points using either the manhattan or euclidean distance.
%% Cell type:markdown id: tags:
![image.png](attachment:image.png)
Source: https://www.researchgate.net/figure/Example-of-Euclidean-and-Manhattan-distances-between-two-points-A-and-B-The-Euclidean_fig8_333430988
%% Cell type:markdown id: tags:
### Review: NamedTuples
We create a namedtuple `Point` with named attributes `x` and `y`. We then create lists of points we want to calculate distances between
%% Cell type:code id: tags:
``` python
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
left_points = [
Point(0, 0),
Point(3, 3),
Point(2, 2),
# TODO: Add another point!
]
right_points = [
Point(5, 5),
Point(0, 3),
Point(2, 2),
# TODO: Add another point!
]
```
%% Cell type:markdown id: tags:
### Complete the function `calculate_distances`
%% Cell type:markdown id: tags:
We already did the math behind `manhattan_distance` and `euclidean_distance` for you!
**Hint:** `distance_algo` should be a reference to a function that calculates distance between two points.
Then, call calculate_distances measuring first in manhattan_distance, then euclidean_distance.
%% Cell type:code id: tags:
``` python
import math
def manhattan_distance(point1, point2):
dist_x = abs(point1.x - point2.x)
dist_y = abs(point1.y - point2.y)
return dist_x + dist_y
def euclidean_distance(point1, point2):
dist_x = (point1.x - point2.x) ** 2
dist_y = (point1.y - point2.y) ** 2
return math.sqrt(dist_x + dist_y)
# TODO: Complete this function!
def calculate_distances(distance_algo):
pass
# TODO: Calculate the distance between the points using manhattan distance
# TODO: Calculate the distance between the points using euclidean distance
```
%% Cell type:markdown id: tags:
### Explain the default use of sorted() on lists of tuples, and on dictionaries.
%% Cell type:code id: tags:
``` python
# first... did you know that sort/sorted takes a 2nd argument called reverse?
populations = [55, 77, 33, 99, 22]
# TODO: sort populations in reverse
```
%% Cell type:code id: tags:
``` python
# Sorting part 1....how are lists of tuples sorted?
# olympic womens hockey badgers...first, last, age
owhockey_badgers = [ ("Hillary", "Knight", 32 ),
("Brianna", "Decker", 30),
("Amanda", "Kessel", 30),
("Alex", "Cavalenni", 30),
("Caroline", "Harvey", 19),
("Abbey", "Roque", 24)
]
# call sorted on this list of tuples
sorted(owhockey_badgers)
# what did this make? How was it sorted?
```
%% Output
[('Abbey', 'Roque', 24),
('Alex', 'Cavalenni', 30),
('Amanda', 'Kessel', 30),
('Brianna', 'Decker', 30),
('Caroline', 'Harvey', 19),
('Hillary', 'Knight', 32)]
%% Cell type:code id: tags:
``` python
# sorting part 2: define a function that returns a value from a tuple
def select0(some_tuple): # function must have exactly one parameter
return some_tuple[0]
def select1(some_tuple):
return some_tuple[1]
def select2(some_tuple):
return some_tuple[2]
# Test these functions on the tuple ("Mike", "Gurmail", "Cole")
```
%% Cell type:code id: tags:
``` python
# call sorted using the 'key' argument
# sort and sorted can take a parameter named key
# key is a reference to a function!
sorted(owhockey_badgers, key=select2)
```
%% Cell type:code id: tags:
``` python
# sort the list of tuples based on the last name
```
%% Cell type:code id: tags:
``` python
# sort the list of tuples based on the age
```
%% Cell type:markdown id: tags:
### Using `lambda`
- `lambda` functions are a way to abstract a function reference
- lambdas are simple functions with:
- multiple possible parameters
- single expression line as the function body
- lambdas are useful abstractions for:
- mathematical functions
- lookup operations
- lambdas are often associated with a collection of values within a list
- Syntax:
```python
lambda parameters: expression
```
%% Cell type:code id: tags:
``` python
# sorting part 3....using lambdas
'''
def no_name(each_tuple):
return each_tuple[-1]
'''
sorted(owhockey_badgers, key = lambda each_tuple : each_tuple[-1])
# read the lambda as: my no-name function has each_tuple as a parameter
# and returns each_tuple[-1] (the last element)
# the variable 'each_tuple' is like a function parameter
```
%% Cell type:code id: tags:
``` python
# TODO: sort the list by the length of the first name
'''
def no_name(x):
return len(x[0])
'''
```
%% Output
'\ndef no_name(x):\n return len(x[0])\n'
%% Cell type:code id: tags:
``` python
# TODO: Sort the list by the length of their full name
```
%% Cell type:markdown id: tags:
### OK, I can sort a list of tuples....what about a list of dictionaries?
%% Cell type:code id: tags:
``` python
hurricanes = [
{"name": "Calvin", "year": 2000},
{"name": "Alexandria", "year": 1980, "speed": 100},
{"name": "Blanc", "year": 1990, "speed": 250},
]
# call sorted on hurricanes and use a lambda expression to grab the year
sorted(hurricanes, key = lambda d : d["year"], reverse=True)
```
%% Output
[{'name': 'Calvin', 'year': 2000},
{'name': 'Blanc', 'year': 1990, 'speed': 250},
{'name': 'Alexandria', 'year': 1980, 'speed': 100}]
%% Cell type:code id: tags:
``` python
# sort hurricanes alphabetically by name
# for you to do on your own...see the above example
```
%% Cell type:code id: tags:
``` python
# on your own, sort hurricanes by speed.....
```
%% Cell type:markdown id: tags:
### This is all great, but what I'd really like to do is to sort dictionaries!
%% Cell type:code id: tags:
``` python
menu = { 'pie': 3.95,
'ala mode':1.50,
'donut': 1.25,
'cookie': 0.79,
'milk':1.65,
'loaf': 5.99,
'hot dog': 4.99}
# sorted (dict) returns a list of the keys sorted
sorted(menu)
```
%% Cell type:code id: tags:
``` python
# but we can make progress on this by using the .items() method
menu.items()
```
%% Cell type:code id: tags:
``` python
# that looks like a list of tuples!
# let's sort menu.items() the same way we sorted a list of tuples
sorted(menu.items(), key = lambda t : t[0] ) # set the sorting key to a lambda expressoin
```
%% Cell type:code id: tags:
``` python
# now let's turn this list of tuples into a dict
dict(sorted(menu.items(), key = lambda t : t[0]))
```
%% Cell type:code id: tags:
``` python
# can you change the previous code to sort by price?
```
%% Cell type:code id: tags:
``` python
# can you sort the dictionary by the length of the name?
```
%% Cell type:markdown id: tags:
## After Lecture
%% Cell type:code id: tags:
``` python
# Practice sorting a list of tuples
# Practice sorting a list of dictionaries
# Practice sorting a dictionary by keys
# Practice sorting a dictionary by values
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment