Skip to content

Week 3 - Functions

Python 3 Functions

Introduction

  • Built-in functions (e.g., int, float) and modules (e.g., math).
    • The primary purpose of Python’s built-in functions is to provide essential functionalities that are commonly used in programming tasks.
    • Built-in functions are generally FASTER than pure Python functions for the following reasons:
      1. Implementation in C avoids Interpreter Overhead: Most built-in functions in Python are implemented in C, which is a lower-level language known for its speed and efficiency.
        • C code is typically compiled into machine code that can be executed directly by the CPU, making it faster than interpreted Python code.
      2. They leverage Hardware Capabilities: Built-in functions generally leverage hardware capabilities like vectorization or SIMD instructions to perform operations more efficiently because of their compiled nature.
      3. Optimization: Python’s developers have optimized the implementation of built-in functions for performance.
        • They often use techniques like algorithmic improvements, caching, and inline expansion to reduce overhead and improve execution speed.
      4. The are Specialized: Built-in functions are tailored for specific tasks and are often optimized for those particular use cases.
        • The len() function is highly optimized for determining the length of a sequence
        • The abs() function is optimized for calculating the absolute value of a number.
  • Why are we talking about functions?
    • Increased code clarity
    • Reusability
    • Modularity by dividing and conquering a problem
  • You will also see for loops for repetition in this week’s chapter!

Defining Functions

Function definition syntax using def:

  • Keyword def: means define
  • Function name: has to follow variable naming conventions
  • Parentheses: parameters go insed and store the data we pass to a function. Empty for no params.
  • Colon (:): Always end a function definition with a :
  • Body: All the properly indented statements after the header.
    • Simple example print_lyrics
      • Displays Monty Python song lyrics:
        1
        2
        3
        def print_lyrics():
            print("I'm a lumberjack, and I'm okay.")
            print("I sleep all night and I work all day.")
        

Calling Functions (just like built-in functions)

1
print_lyrics()

What’s a Function Object?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Here is a function definition
def greet(name):
    print("Hello, " + name + "!")

# Assigning the function object to a variable
say_hello = greet

# Calling the function using the variable
say_hello("Alice")  # Output: Hello, Alice!

# Passing the function object as an argument to another function
def call_function(func, name):
    func(name)

call_function(greet, "Bob")  # Output: Hello, Bob!

Parameters and Arguments

  • Parameters are Placeholders in the function definition that behave like local variables.
  • Arguments are the values passed when calling the function
    • Variables can be passed as arguments.
    • We should already know this, think print(my_var)
  • Functions can have multiple parameters meaning you will pass multiple arguments (e.g., repeat(word, n) below)
    • Later we will see functions can have unlimited arguments that get packed and unpacked.
  • It is critical to understand that argument values get copied to parameters within the function body:
    1
    2
    3
    4
    5
    def repeat(word, n):
        print(word * n)
    
    spam = 'Spam, '
    repeat(spam, 4)  # Output: Spam, Spam, Spam, Spam,
    

Function Nesting and Decomposition

  • You may call functions from within other functions, see our examples below.
  • Function nesting is one way to break down complex tasks
    • Consider the code below (e.g., print_verse using repeat and first_two_lines, last_three_lines)
    • This process of breaking down tasks is known as Decomposition
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def first_two_lines():
    repeat(spam, 4)
    repeat(spam, 4)

def last_three_lines():
    repeat(spam, 2)
    print('(Lovely Spam, Wonderful Spam!)')
    repeat(spam, 2)

def print_verse():
    first_two_lines()
    last_three_lines()
  • Let’s look at a well-designed set of functions to show modularity and reusability:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    def calculate_circle_area(radius):
        pi = 3.14159
        return pi * radius * radius
    
    def calculate_square_area(side_length):
        return side_length * side_length
    
    def calculate_rectangle_area(width, height):
        return width * height
    
    def calculate_area(shape, **kwargs):
        if shape == "circle":
            return calculate_circle_area(**kwargs)
        elif shape == "square":
            return calculate_square_area(**kwargs)
        elif shape == "rectangle":
            return calculate_rectangle_area(**kwargs)
        else:
            raise ValueError(f"Unknown shape: {shape}")
    
    # Example usage
    radius = 5
    side_length = 10
    width = 8
    height = 6
    
    circle_area = calculate_area("circle", radius=radius)
    square_area = calculate_area("square", side_length=side_length)
    rectangle_area = calculate_area("rectangle", width=width, height=height)
    
    print("Circle area:", circle_area)
    print("Square area:", square_area)
    print("Rectangle area:", rectangle_area)
    

First Glimpse at Repetition

For Loop Syntax

  • Keyword for
  • Loop variable
  • Keyword in
  • Iterable object (e.g., range(n))
  • Colon (:)
  • Body (indented statements)

For Loop Examples:

1
2
3
for i in range(2):
    print(i)  # Output: 0
             #        1
1
2
for i in range(2):
    print_verse()

Nesting for Loops and Functions

1
2
3
def print_n_verses(n):
    for i in range(n):
        print_verse()

Nesting for Loops and for Loops

1
2
3
4
5
6
7
8
rows = 10
columns = 10

for i in range(1, rows + 1):
    for j in range(1, columns + 1):
        product = i * j
        print(f"{i} x {j} = {product}", end="\t")
    print()

Local Scope

  • Local variables
    • Created within a function.
    • Accessible only within the function.
    • Pop off the stack (i.e. go away) when the function returns.
  • Errors are thrown when trying to access local variables outside the function scope

Examples

1
2
3
4
5
6
7
8
9
def cat_twice(part1, part2):
    cat = part1 + part2
    print_twice(cat)

line1 = 'Always look on the '
line2 = 'bright side of life.'
cat_twice(line1, line2)  # Output: Always look on the bright side of life.

print(cat)  # This would raise a NameError
* Treat parameters like local scoped variables as well.

Debugging

Stack Diagrams

  • Let’s revisit Python Tutor
    • Visualize function calls and variable scope.
    • Look at stack/frames representing functions and their local variables.
    • Look at the above cat_twice example to gain understanding of previous concepts.

Tracebacks

  • Tracebacks are error messages listing the function call stack.
  • Let’s look at print_twice below, which throws a NameError, to view a traceback:
1
2
3
def print_twice(string):
    print(cat)  # NameError
    print(cat)
  • As you should see, the traceback shows the sequence of functions leading up to the error.

More Debugging Help

  • Debugging is just problem-solving and experimentation.
    • Use print statements for skaffolding
    • Use IDE breakpoints and debugger tools
  • A good practice to create bug free code is ta start with a working program and make small modifications.
  • Peer code reviews and AI Chatbots are also great debugging tools

Recap on the Benefits of Functions

  • Improved code readability and maintainability through clear naming.
  • Reduced code duplication and easier updates through centralized function changes.
  • Easier debugging by focusing on individual functions.
  • Reusability across different programs.

Terms the Book thinks you should know

  • Look these up as an excercise, or quiz yourself out loud!
  • function definition
  • header
  • body
  • function object
  • parameter
  • loop
  • local variable
  • stack diagram
  • stack/frame
  • traceback