Lab 4: Lambdas and Dictionaries
Due at 11:59:59 pm on 02/20/2024.
Starter Files
Download lab04.zip. Inside the archive, you will find starter files for the questions in this lab, along with a copy of the OK autograder.
Lambda
Lambda expressions are one-line functions that specify two things:
the parameters and the return value.
lambda <parameters>: <return value>
While both lambda and def statements are related to functions, there are some differences.
| lambda | def | |
|---|---|---|
| Type | lambda is an expression |
def is a statement |
| Description | Evaluating a lambda expression does not create or modify any variables.
Lambda expressions just create new function objects. |
Executing a def statement will create a new function object and bind it to a variable in the current environment. |
| Example | |
|
A lambda expression by itself is not very interesting. As with any objects such as numbers, booleans, strings, we usually:
- assign lambda to variables (
foo = lambda x: x) - pass them in to other functions (
bar(lambda x: x)) - return them as the results of other functions (
return lambda x: x) - return them as the results of other lambdas (
lambda x: lambda y: x + y)
In the final example above, the outer lambda (lambda x) takes in a value x, and it
returns another lambda (lambda y) that takes an argument y and returns x+y.
Environment Diagrams
Environment diagrams are one of the best learning tools for understanding
lambda expressions because you're able to keep
track of all the different names, function objects, and arguments to functions.
We highly recommend drawing environment diagrams or using Python
tutor if you get stuck doing the WWPD problems below.
For examples of what environment diagrams should look like, try running some
code in Python tutor. Here are the rules:
Lambdas
Note: As we saw in the
lambdaexpression section above,lambdafunctions have no intrinsic name. When drawinglambdafunctions in environment diagrams, they are labeled with the namelambdaor with the lowercase Greek letter λ. This can get confusing when there are multiple lambda functions in an environment diagram, so you can distinguish them by numbering them or by writing the line number on which they were defined.
- Draw the lambda function object and label it with λ, its formal parameters, and its parent frame. A function's parent frame is the frame in which the function was defined.
This is the only step. We are including this section to emphasize the fact that
the difference between lambda expressions and def statements is that
lambda expressions do not create any new bindings in the environment.
WWPD
Question 1: WWPD: Lambda the Free
Use Ok to test your knowledge with the following "What Would Python Display?" questions:
python3 ok -q lambda -uFor all WWPD questions, type
Functionif you believe the answer is<function...>,Errorif it errors, andNothingif nothing is displayed. As a reminder, the following two lines of code will not display anything in the Python interpreter when executed:>>> x = None >>> x
>>> lambda x: x # A lambda expression with one parameter x
______<function <lambda> at ...>
>>> a = lambda x: x # Assigning the lambda function to the name a
>>> a(5)
______5
>>> (lambda: 3)() # Using a lambda expression as an operator in a call exp.
______3
>>> b = lambda x: lambda: x # Lambdas can return other lambdas!
>>> c = b(88)
>>> c
______<function <lambda> at ...
>>> c()
______88
>>> d = lambda f: f(4) # They can have functions as arguments as well.
>>> def square(x):
... return x * x
>>> d(square)
______16
>>> z = 3
>>> e = lambda x: lambda y: lambda: x + y + z
>>> e(0)(1)()
______4
>>> f = lambda z: x + z
>>> f(3)
______NameError: name 'x' is not defined
>>> higher_order_lambda = lambda f: lambda x: f(x)
>>> g = lambda x: x * x
>>> higher_order_lambda(2)(g) # Which argument belongs to which function call?
______Error
>>> higher_order_lambda(g)(2)
______4
>>> call_thrice = lambda f: lambda x: f(f(f(x)))
>>> call_thrice(lambda y: y + 1)(0)
______3
>>> print_lambda = lambda z: print(z) # When is the return expression of a lambda expression executed?
>>> print_lambda
______Function
>>> one_thousand = print_lambda(1000)
______1000
>>> one_thousand
______# print_lambda returned None, so nothing gets displayed
Lambdas
Question 2: Exponents Are Fun
Using a lambda expression, complete the exponent_fun function. This function should take an argument exponent and returns the base raised to that exponent. The body of the function must be one line long!
def exponent_fun(exponent):
"""
Returns a function that takes one argument and returns the
base raised to that exponent.
>>> square = exponent_fun(2)
>>> square(5)
25
>>> cubed = exponent_fun(3)
>>> cubed(2)
8
"""
"*** YOUR CODE HERE ***"
return lambda base: base ** exponent
Use OK to test your code:
python3 ok -q exponent_fun
Question 3: Compare Lambda
Write a function that returns a subtraction lambda function or addition lambda
function depending on the operator passed into compare_lambda. The lambda
functions you create should take in two arguments. If a user passes in an invalid
operator, use a lambda function to return "Remember to only use + or -!".
def compare_lambda(operator):
"""
Write a function that returns a subtraction lambda
function or addition lambda function depending on
the operator passed into compare lambda. Both lambda
functions take in two arguments.
>>> adding = compare_lambda("+")
>>> adding(3,2)
5
>>> subtracting = compare_lambda("-")
>>> subtracting(6,2)
4
>>> operator_not_supported = compare_lambda("*")
>>> operator_not_supported(2,3)
'Remember to only use + or -!'
"""
"*** YOUR CODE HERE ***"
if operator == "-":
return lambda x, y: x - y
elif operator == "+":
return lambda x, y: x + y
else:
return lambda x, y: 'Remember to only use + or -!'
Use OK to test your code:
python3 ok -q compare_lambda
Dictionaries
Question 4: Flip Dictionary
Implement the function flip_dict which takes in a dictionary and returns a similar dictionary where the values have become the keys and the keys have become the values.
In this problem, you can assume that each key value pair is unique, and no key or value will be repeated or used more than once.
def flip_dict(dictionary):
"""Returns a flipped version of the original dictionary.
>>> TAs = {"12pm-2pm": "sean", "4pm-6pm": "rebecca", "2pm-4pm": "lily"}
>>> flipped_TAs = flip_dict(TAs)
>>> flipped_TAs
{'sean': '12pm-2pm', 'rebecca': '4pm-6pm', 'lily': '2pm-4pm'}
"""
"*** YOUR CODE HERE ***"
result_dict = {}
for key in dictionary:
value = dictionary[key]
result_dict[value] = key
return result_dict
Use OK to test your code:
python3 ok -q flip_dict
Question 5: Build the Full Roster
Implement the function common_players. The common_players function takes in a roster dictionary and identifies which keys share the same values. The function returns a new dictionary of this structure:
- Keys: The values from the
rosterdictionary - Values: A list of keys from
rosterthat share that same value.
def common_players(roster):
"""Returns a dictionary containing values along with a corresponding
list of keys that had that value from the original dictionary.
>>> full_roster = {"bob": "Team A", "barnum": "Team B", "beatrice": "Team C", "bernice": "Team B", "ben": "Team D", "belle": "Team A", "bill": "Team B", "bernie": "Team B", "baxter": "Team A"}
>>> player_dict = common_players(full_roster)
>>> dict(sorted(player_dict.items()))
{'Team A': ['bob', 'belle', 'baxter'], 'Team B': ['barnum', 'bernice', 'bill', 'bernie'], 'Team C': ['beatrice'], 'Team D': ['ben']}
"""
"*** YOUR CODE HERE ***"
result_dict = {}
for player in roster:
team = roster[player]
if team in result_dict:
result_dict[team] += [player]
else:
result_dict[team] = [player]
return result_dict
Use OK to test your code:
python3 ok -q common_players
Submission
When you are done, submit your file to Gradescope. You only need to upload the following files:
lab04.py