COMP1701-004

fall 2023

lec-08

What do we have here?

about that midterm

Marc Schroeder is present in class today and is conducting observations as part of an approved research study. No audio or video recording is being conducted.

 

His fieldnotes may record general observations about the overall nature of classroom activities and discussions. However, these will not include personal or identifying details about individuals or their participation, except for those students who are participating in other aspects of the study.

 

If you have any questions or concerns, then please let me know, and I’ll direct you to the appropriate resource.

RECALL time

def displayWelcome():
  print("-" * 20)
  print(f'''{"Welcome!":^20}''')
  print("-" * 20)

Here are the contents of a script:

  1. What will happen when we run this script? Be careful.
  2. How would you change the script so that it displays the welcome?
  3. What does displayWelcome() return?
  4. What does displayWelcome() do?
  5. What category of function is this?
  6. If we added type hints to the function, what would it look like?
  7. Does the function follow PEP8 naming conventions?
def display_welcome(name):
  greeting = f'''Welcome, {name}'''
  return f'''{greeting:<30}'''

Here are the contents of a script:

  1. What will happen when we run this script?
  2. How would you change the script so that it displays the welcome?
  3. What does display_welcome() return?
  4. What does display_welcome() do?
  5. What category of function is this?
  6. If we added type hints to the function, what would it look like?
  7. Does the function follow PEP8 naming conventions?
  8. Is the function named well? Explain.

let's talk about these  things today:

 your pal, Python Tutor

 lots of tracing

 your other pal, the debugger

Prolly not gonna make it here.

Python Tutor is the
bestest pal ever

If I may be so bold, bookmark this:

This particular hacked link opens it up in a workspace ready for you to paste code in.

This is the same tool that's used in the textbook when it shows the CodeLens button

You are using the textbook, right?
Please tell me you're using the textbook.

What's so great about this tool?

It's a great way to check that YOU, human, are doing traces correctly.

It's NOT useful  to mindlessly  Next > Next > Next
through the trace to get to the "answer".

You're better than that.

(Besides, you ain't gonna have it with you on the midterms and final, right?)

let's trace together

Practicing tracing is about paying your dues.

No free lunch here.

No shortcuts.

No cheat codes.

value-returning function practice trace

def desired_volume():
  return 11

volume = desired_volume()

Trace this snippet, showing intermediate values of all variables, as well as any output.

How would the header look if you were asked to use type hints?

value-returning function practice trace

def length_diff(s1, s2):
  diff = len(s1) - len(s2)
  return abs(diff)

d = length_diff("Yo.", "Hi there.")
print(f'Those differ by {d}.')

len() is a built-in function that returns the length (in characters) of a string

abs() is a built-in function that returns the absolute value of the number provided

Trace this snippet, showing intermediate values of all variables, as well as any output.

How would the header look if you were asked to use type hints?

What kind of variable is diff?

let's talk parameters

def length_diff(s1: str, s2: str) -> int:
  diff = len(s1) - len(s2)
  return abs(diff)

length_diff("Hi there.")

length_diff("Hi", "there.", "Sup?")

length_diff("", "      ")

Let's play.

Is this OK?

This?

How 'bout this?

Most languages make sure that the number of arguments in a function call match the number of parameters in the corresponding function definition.

Based on what you see here, does Python?

let's talk parameters

def length_diff(s1: str, s2: str) -> int:
  diff = len(s1) - len(s2)
  return abs(diff)

length_diff(3, 17)

length_diff("yo", 1.43)

length_diff("", "Hi!" + "😁")

length_diff(f'''{12:10}''', str(12.43))

Let's play a bit more.

Is this OK?

This?

How 'bout this?

Most languages make sure that the type of arguments in a function call match the type of parameters in the corresponding function definition.

Based on what you see here, does Python?

This cool?

Order is important.

Always follow the flow of execution.

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  
main()

What will happen if we switch the order of statements like this?

def main():
  a = 10
  b = 2
  c = 3
  print(a, b, c, d)
  d = 4

main()

?

UnboundLocalError: cannot access local variable 'd' where it is not associated with a value

Don't flee from the traceback.

Run this in a Codespace.

 

Read the traceback.

def main():
  a = 10
  b = 2
  c = 3
  print(a, b, c, d)
  d = 4

main()

Embrace it. (Or at least give it a grudging side-hug.)

Oh joy. Another term.

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)
  
main()

A slightly beefy trace.

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)
  
main()

What will happen if we switch the order of things like this?

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

main()

the ole switcharoo!

Is this OK?!?!

What will happen if we switch the order of things this way?

?

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)
  
main()
main()

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)
main()

def silly(a,b,c):
  c = a + b
  b = c
  a = 2.0 * a
  d = int(a + b + c)
  print(a, b, c, d)
  return d

def main():
  a = 10
  b = 2
  c = 3
  d = 4
  print(a, b, c, d)
  d = silly(b, a, c)
  print(a, b, c, d)

Run this in a Codespace.

Read the traceback.

NameError: name 'main' is not defined.

Python is getting all accusatory:
"main?!? You haven't told me about any 'main'. I'm not a mind reader you know."

Do you understand why it has a point?

scope

scope

the scope of a variable is "where/when an identified item (like a variable, a function etc.) is recognizable and accessible"

-Ze Textbook (section 4.8)

scope

def foo():
  foo_name = "foo"
  print(foo_name)

def bar():
  bar_name = "bar"
  peek_at_foo_name = foo_name
  print(bar_name)
  print("That foo() guy's foo_name:", peek_at_foo_name)
  
def main():
  foo()
  bar()

main()

Predict what's going to happen - keep it secret.

scope

Functions can't "see" inside other functions - they can't access another function's local variables, because they are "out of scope"

def foo():
  foo_name = "foo"
  print(foo_name)

def bar():
  bar_name = "bar"
  peek_at_foo_name = foo_name
  print(bar_name)
  print("That foo() guy's foo_name:", peek_at_foo_name)
  
def main():
  foo()
  bar()

main()

Throw this expression around to sound like you know what you're doing.

Hold on there, cowboy.

scope

But.

Of course there's a but. It's Wednesday.

foo_name = "a global foo"

def foo():
  foo_name = "foo"
  print(foo_name)

def bar():
  bar_name = "bar"
  peek_at_foo_name = foo_name
  print(bar_name)
  print("The foo_name I CAN see:", peek_at_foo_name)
  
def main():
  foo()
  bar()

main()

Predict what's going to happen this time - but don't ruin the surprise.

foo_name = "a global foo"

def foo():
  foo_name = "foo"
  print(foo_name)

def bar():
  bar_name = "bar"
  peek_at_foo_name = foo_name
  print(bar_name)
  print("The foo_name I CAN see:", peek_at_foo_name)
  
def main():
  foo()
  bar()

main()

Functions CAN "see" inside the global scope - these global variables are always "in scope".

MM_PER_CM = 10

def get_side_len_cm() -> float:
  len_as_text = input("Length of side in cm? ")
  return float(len_as_text)
  
def squarea(side_len: float) -> float:
  return side_len ** 2

def display_result(side_len: float, area: float) -> None:
  print(f"A {side_len}cm square has this area: {area:.1f}mm^2")
  
side_len_cm = get_side_len_cm()
side_len_mm = side_len_cm * MM_PER_CM
area = squarea(side_len_mm)
display_result(side_len_cm, area)

Trace this code

Assume the user enters 3 when prompted.

let's see what you got

PTS_PER_GOLD = 3
PTS_PER_SILVER = 2
PTS_PER_BRONZE = 1

def gold_pts(g):
  g = g + 1
  return g * PTS_PER_GOLD

def silver_pts(s):
  s = s - 1
  return s * PTS_PER_SILVER

def bronze_pts(b):
  b = b # No, this doesn't make sense.
  return b * PTS_PER_BRONZE

def total_pts(g,s,b):
  return gold_pts(g) + silver_pts(s) + bronze_pts(b)

def main():
  g = 1
  s = 2
  b = 3
  print(g,s,b)
  tp = total_pts(g,s,b)
  print(tp,b,s,g)

g = 3
s = 1
b = 2

main()

print(g,s,b)
  1. List the global variables.
  2. List the local variables.
  3. Add type hints.
  4. Name all the value-returning functions (including built-ins).
  5. Name all the void functions (including built-ins).
  6. How many function calls are there?
  7. How many assignment statements?
  8. How many function definitions?

Review Q's

the debugger

yeah, as if we'll have time to get here

lec-08

By Jordan Pratt

lec-08

Python Tutor | tracing out the wazoo

  • 340