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:
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.")
- Displays Monty Python song lyrics:
- Simple example
Calling Functions (just like built-in functions)¶
1 |
|
What’s a Function Object?¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
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
usingrepeat
andfirst_two_lines
,last_three_lines
) - This process of breaking down tasks is known as Decomposition
- Consider the code below (e.g.,
1 2 3 4 5 6 7 8 9 10 11 12 |
|
- 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 |
|
1 2 |
|
Nesting for
Loops and Functions¶
1 2 3 |
|
Nesting for
Loops and for
Loops¶
1 2 3 4 5 6 7 8 |
|
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 |
|
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 |
|
- 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