Discussion 1: Control, Environment Diagrams
Files: disc01.pdf
This is an online worksheet that you can work on during discussions. Your work is not graded and you do not need to submit anything.Control structures
Control structures direct the flow of a program using logical
statements. For example, conditionals (if-elif-else)
allow a program to skip sections of code, and iteration (while),
allows a program to repeat a section.
Conditional statements
Conditional statements let programs execute different lines
of code depending on certain conditions. Let’s review the
if-elif-else syntax:
-
The
elifandelseclauses are optional, and you can have any number ofelifclauses. -
A conditional expression is an expression that evaluates to
either a truthy value (
True, a non-zero integer, etc.) or a falsy value (False,0,None,"",[], etc.). -
Only the suite that is indented under the first
if/elifwhose conditional expression evaluates to a true value will be executed. -
If none of the conditional expressions evaluate to a true value, then the
elsesuite is executed. There can only be oneelseclause in a conditional statement.
Here's the general form:
if <conditional expression>:
<suite of statements>
elif <conditional expression>:
<suite of statements>
else:
<suite of statements>
Boolean Operators
Python also includes the boolean operators and,
or, and not. These operators are used to combine and
manipulate boolean values.
-
notreturns the opposite boolean value of the following expression, and will always return eitherTrueorFalse. -
andevaluates expressions in order and stops evaluating (short-circuits) once it reaches the first falsy value, and then returns it. If all values evaluate to a truthy value, the last value is returned. -
orevalutes expressions in order and short-circuits at the first truthy value and returns it. If all values evaluate to a falsy value, the last value is returned.
For example:
>>> not None
True
>>> not True
False
>>> -1 and 0 and 1
0
>>> False or 9999 or 1/0
9999
Q1: Jacket Weather?
Alfonso will only wear a jacket outside if it is below 60 degrees or it is raining.
Write a function that takes in the current temperature and a boolean value
telling if it is raining. This function should return True if
Alfonso will wear a jacket and False otherwise.
First, try solving this problem using an if statement.
Note that we’ll either return True or False based on
a single condition, whose truthiness value will also be either
True or False. Knowing this, try to write this
function using a single line.
Q2: Case Conundrum
In this question, we will explore the difference between
if and elif.
What is the result of evaluating the following code?
def special_case():
x = 10
if x > 0:
x += 2
elif x < 13:
x += 3
elif x % 2 == 1:
x += 4
return x
special_case()
What is the result of evaluating this piece of code?
def just_in_case():
x = 10
if x > 0:
x += 2
if x < 13:
x += 3
if x % 2 == 1:
x += 4
return x
just_in_case()
How about this piece of code?
def case_in_point():
x = 10
if x > 0:
return x + 2
if x < 13:
return x + 3
if x % 2 == 1:
return x + 4
return x
case_in_point()
Which of these code snippets result in the same output, and why? Based on your
findings, when do you think using a series of
if statements has the same effect as using both
if and elif cases?
Q3: If Function vs Statement
Now that we've learned about how if statements work, let's see if
we can write a function that behaves the same as an if statement.
def if_function(condition, true_result, false_result):
"""Return true_result if condition is a true value, and
false_result otherwise.
>>> if_function(True, 2, 3)
2
>>> if_function(False, 2, 3)
3
>>> if_function(3==2, 'equal', 'not equal')
'not equal'
>>> if_function(3>2, 'bigger', 'smaller')
'bigger'
"""
if condition:
return true_result
else:
return false_result
Despite the doctests above, this function actually does not do the
same thing as an if statement in all cases.
To demonstrate this, we want to find a case where this function will behave
differently from an if statement. To do so in this problem,
implement the following,
cond: This should act as the "condition" of the "if".-
true_func: This should represent what we would want the result of the "if" to be in the case that the "condition" is truthy. -
false_func: This should represent what we would want the result of the "if" to be in the case that the "condition" is falsy.
so that with_if_function does not behave the same as
with_if_statement, namely as specified in their doctests:
-
When
with_if_statementis called, we print out61A. -
When
with_if_functionis called, we print out bothWelcome toand61Aon separate lines.
Implement cond, true_func, and
false_func below.
Run in 61A CodeHint: If you are having a hard time identifying how
with_if_statementandwith_if_functionwould differ in behavior, consider the rules of evaluation forifstatements and call expressions.
While loops
To repeat the same statements multiple times in a program, we can use iteration. In Python, one way we can do this is with a while loop.
while <conditional clause>:
<statements body>
As long as <conditional clause> evaluates to a true value,
<statements body> will continue to be executed. The
conditional clause gets evaluated each time the body finishes executing.
Q4: Square So Slow
What is the result of evaluating the following code?
def square(x):
print("here!")
return x * x
def so_slow(num):
x = num
while x > 0:
x=x+1
return x / 0
square(so_slow(5))
Hint: What happens to
xover time?
Q5: Is Prime?
Write a function that returns True if a positive integer
n is a prime number and False otherwise.
A prime number n is a number that is not divisible by any numbers other than 1 and n itself. For example, 13 is prime, since it is only divisible by 1 and 13, but 14 is not, since it is divisible by 1, 2, 7, and 14.
Run in 61A CodeHint: Use the
%operator:x % yreturns the remainder ofxwhen divided byy.
Q6: Fizzbuzz
Implement the fizzbuzz sequence, which prints out a
single statement for each number from 1 to n. For a
number i,
- If
iis divisible by 3 only, then we print "fizz". - If
iis divisible by 5 only, then we print "buzz". -
If
iis divisible by both 3 and 5, then we print "fizzbuzz". - Otherwise, we print the number
iby itself.
Implement fizzbuzz(n) here:
Environment Diagrams
An environment diagram is a model we use to keep track of all the variables that have been defined and the values they are bound to. We will be using this tool throughout the course to understand complex programs involving several different assignments and function calls.
Here's a short program and its corresponding diagram:
Remember that programs are mainly just a set of statements or instructions—so drawing diagrams that represent these programs also involves following sets of instructions! Let’s dive in...
Assignment Statements
Assignment statements, such as x = 3, define variables in
programs. To execute one in an environment diagram, record the variable name
and the value:
- Evaluate the expression on the right side of the
=sign. - Write the variable name and the expression’s value in the current frame.
Q7: Assignment Diagram
Use these rules to draw an environment diagram for the assignment statements below:
x = 11 % 4
y = x
x **= 2
def Statements
A def statement creates ("defines") a function object and binds
it to a name. To diagram def statements, record the function name
and bind the function object to the name. It’s also important to write the
parent frame of the function, which is where the function is
defined.
A very important note: Assignments for
def statements use pointers to functions, which can have
different behavior than primitive assignments (such as variables bound to
numbers).
-
Draw the function object to the right-hand-side of the frames, denoting the
intrinsic name of the function, its parameters, and the parent frame (e.g.
func square(x) [parent = Global]. - Write the function name in the current frame and draw an arrow from the name to the function object.
Q8: def Diagram
Use these rules for defining functions and the rules for assignment statements to draw a diagram for the code below.
def double(x):
return x * 2
def triple(x):
return x * 3
hat = double
double = triple
Call Expressions
Call expressions, such as square(2), apply
functions to arguments. When executing call expressions, we create a new frame
in our diagram to keep track of local variables:
- Evaluate the operator, which should evaluate to a function.
- Evaluate the operands from left to right.
-
Draw a new frame, labelling it with the following:
-
A unique index (
f1,f2,f3, ...). -
The intrinsic name of the function, which is the name
of the function object itself. For example, if the function object is
func square(x) [parent=Global], the intrinsic name issquare. - The parent frame ([
parent=Global]).
-
A unique index (
-
Bind the formal parameters to the argument values obtained in step 2 (e.g.
bind
xto 3). - Evaluate the body of the function in this new frame until a return value is obtained. Write down the return value in the frame.
If a function does not have a return value, it implicitly returns
None. In that case, the “Return value” box should contain
None.
Note: Since we do not know how built-in functions like
min(...) or imported functions like add(...) are
implemented, we do not draw a new frame when we call them, since we would not
be able to fill it out accurately.
Q9: Call Diagram
Let’s put it all together! Draw an environment diagram for the following code. You may not have to use all of the blanks provided to you.
def double(x):
return x * 2
hmmm = double
wow = double(3)
hmmm(wow)
| Return value |
| Return value |
Q10: Nested Calls Diagrams
Draw the environment diagram that results from executing the code below. You may not need to use all of the frames and blanks provided to you.
def f(x):
return x
def g(x, y):
if x(y):
return not y
return y
x = 3
x = g(f, x)
f = g(f, 0)
| Return value |
| Return value |
| Return value |
| Return value |