CMU 15-112: Fundamentals of Programming and Computer Science
Class Notes: Writing Functions


  1. Vocabulary
  2. Return Statements
  3. Print versus Return
  4. Different Parameter and Return Types
  5. Function Composition
  6. Helper Functions
  7. Test Functions
  8. Local Variable Scope
  9. Global Variable Scope

  1. Vocabulary
    x = 5 def f(y, z): result = x + y + z return result print(f(1, 2)) # 8 print(f(3, 4)) # 12 # Vocabulary: # global variable # local variable # statement # expression # function definition (or declaration) # function call # parameter (or "formal parameter") # argument # return value # return type

  2. Return Statements
    # Basic example def isPositive(x): return (x > 0) print(isPositive(5)) # True print(isPositive(-5)) # False print(isPositive(0)) # False

    Return ends the function immediately:
    def isPositive(x): print("Hello!") # runs return (x > 0) print("Goodbye!") # does not run ("dead code") print(isPositive(5)) # prints Hello, then True


    No return statement --> return None:
    def f(x): x + 42 print(f(5)) # None

    Another example:
    def f(x): result = x + 42 print(f(5)) # None

  3. Print versus Return
    # This is a common early mistake (confusing print and return): def cubed(x): print(x**3) # Here is the error! cubed(2) # seems to work! print(cubed(3)) # sort of works (but prints None, which is weird) print(2*cubed(4)) # Error!

    Once again (correctly):
    def cubed(x): return (x**3) # That's better! cubed(2) # seems to be ignored (why?) print(cubed(3)) # works! print(2*cubed(4)) # works!

  4. Different Parameter and Return Types
    def hypotenuse(a, b): return ((a**2) + (b**2))**0.5 print(hypotenuse(3, 4)) # 5.0 (not 5) print("---------------------") def xor(b1, b2): return ((b1 and (not b2)) or (b2 and (not b1))) # same as (b1 != b2) print(xor(True, True)) # False print(xor(True, False)) # True print(xor(False, True)) # True print(xor(False, False)) # False print("---------------------") def isPositive(n): return (n > 0) print(isPositive(10)) # True print(isPositive(-1.234)) # False

  5. Function Composition
    def f(w): return 10*w def g(x, y): return f(3*x) + y def h(z): return f(g(z, f(z+1))) print(h(1)) # hint: try the "visualize" feature

  6. Helper Functions
    def onesDigit(n): return n%10 def largerOnesDigit(x, y): return max(onesDigit(x), onesDigit(y)) print(largerOnesDigit(134, 672)) # 4 print(largerOnesDigit(132, 674)) # Still 4

  7. Test Functions
    • A broken test function
      def onesDigit(n): return n%10 def testOnesDigit(): print("Testing onesDigit()...", end="") assert(onesDigit(5) == 5) assert(onesDigit(123) == 3) assert(onesDigit(100) == 0) assert(onesDigit(999) == 9) print("Passed!") testOnesDigit() # Passed! Why is this bad?

    • A better version
      def onesDigit(n): return n%10 def testOnesDigit(): print("Testing onesDigit()...", end="") assert(onesDigit(5) == 5) assert(onesDigit(123) == 3) assert(onesDigit(100) == 0) assert(onesDigit(999) == 9) assert(onesDigit(-123) == 3) # Added this test print("Passed!") testOnesDigit() # Crashed! So the test function worked!

  8. Local Variable Scope
    def f(x): print("In f, x =", x) x += 5 return x def g(x): return f(x*2) + f(x*3) print(g(2))

    Another example:
    def f(x): print("In f, x =", x) x += 7 return round(x / 3) def g(x): x *= 10 return 2 * f(x) def h(x): x += 3 return f(x+4) + g(x) print(h(f(1)))

  9. Global Variable Scope
    # In general, you should avoid using global variables. # You will even lose style points if you use them! # Still, you need to understand how they work, since others # will use them, and there may also be some very few occasions # where you should use them, too! g = 100 def f(x): return x + g print(f(5)) # 105 print(f(6)) # 106 print(g) # 100

    Another example:
    g = 100 def f(x): # If we modify a global variable, we must declare it as global. # Otherwise, Python will assume it is a local variable. global g g += 1 return x + g print(f(5)) # 106 print(f(6)) # 108 print(g) # 102