Day 5: Functions
Review of Control Structures in Python
Control structures are the backbone of any programming language, Python is no exception. They dictate the flow of control in a program. In Python, we primarily use three types of control structures – sequential, selection (or decision making), and iteration (or looping).
Sequential Control Structure
Sequential control is the default control structure where statements are executed line by line, in the order they appear in the script. Here’s a simple example:
print("This is the first line.")
print("This is the second line.")
print("This is the third line.")
In this case, Python executes the print statements one after another in sequence.
Selection Control Structure
In Python, we use if, elif (else if), and else statements for decision-making purposes. The selection structure tests a condition, and then runs one sequence of code if the condition is true, and another if the condition is false.
Here’s a simple example:
temperature = 20
if temperature < 0:
print("It's freezing!")
elif 0 <= temperature < 20:
print("It's cold!")
else:
print("It's warm!")
In this code snippet, Python checks the if condition first. If the condition fails, it checks the elif condition, and if that also fails, it runs the code in the else clause.
Iteration Control Structure
We use loops in Python for repetitive tasks. The two types of loops in Python are for and while.
- For Loop: A
forloop in Python iterates over a sequence (like a list, tuple, string, or range) or other iterable objects.
Here’s a simple for loop:
for i in range(5):
print(i)
This script prints numbers from 0 to 4.
- While Loop: A
whileloop in Python executes a block of code as long as a specified condition is true.
Here’s a simple while loop:
counter = 0
while counter < 5:
print(counter)
counter += 1
This script also prints numbers from 0 to 4.
Remember that loop control statements like break and continue can further influence the flow in loops. The break statement terminates the loop prematurely, while the continue statement skips the rest of the current iteration and goes to the next one.
Introduction to Functions in Python
Definition of Functions
In programming, a function is a reusable piece of code that performs a specific task. Functions help to organize the code, make it more readable, and allow a piece of code to be reused in different parts of a program, or even in different programs.
In Python, a function is defined using the def keyword, followed by a function name, a set of parentheses which may enclose some parameters, and a colon. A block of code indented under the function definition makes up the body of the function. Here’s an example of a simple Python function:
def greet():
print("Hello, World!")
This function, when called, prints out the message “Hello, World!”.
Why Use Functions?
Functions are one of the fundamental building blocks in Python for several reasons:
- Code Reusability: Once a function is defined, it can be used anywhere in your program, reducing the need for writing the same code again and again.
- Modularity: Functions allow you to break down complex problems into smaller, manageable pieces of code. This makes the code easier to understand, test, and debug.
- Abstraction: When using a function, you don’t need to know the details of how the function works to use it. You just need to know what parameters it takes (if any) and what it returns. This is known as abstraction.
- Code Organization: Functions help you organize your code better. For example, you can group related functions in a Python module (a Python file), making your code easier to navigate.
- Maintainability: If you need to make a change to a piece of code that’s repeated throughout your program, you’d have to go and change it everywhere if you didn’t use functions. But if you’ve used a function, you just need to update the function’s code, and the changes will take effect wherever the function is used.
By using functions, you can make your Python programs more efficient, maintainable, and readable. Functions are essential for structured and modular programming.
Defining and Calling Functions in Python
The ‘def’ Keyword
In Python, a function is defined using the def keyword, followed by a unique function name, parentheses (), and a colon :. The statements that form the body of the function start at the next line, and must be indented. Here’s a simple example:
def greet():
print("Hello, World!")
Naming Conventions for Functions
When naming your functions in Python, you should follow these conventions:
- Function names should be lowercase, with words separated by underscores as necessary to improve readability. This is known as snake_case. For example,
calculate_average,get_user_input. - Function names should be descriptive and indicate what the function does. For example,
print_messageis a better name than justmessage. - Avoid using the names of existing Python keywords or functions for your functions to prevent conflicts and confusion.
Calling a Function
Once a function is defined, you can call (or invoke) it by using its name followed by parentheses (). If the function requires arguments (values passed into the function), you would include them in the parentheses. Here’s how to call the greet function we defined earlier:
greet() # Prints: Hello, World!
Practice Exercise: Creating and Calling a Simple Function
Now, let’s practice what we’ve learned by creating and calling a simple function.
Exercise:
- Define a function named
say_hellothat takes one parameter namedname. - Inside the function, print out the message “Hello, [name]!” where [name] is replaced with the value of the
nameparameter. - Call this function with your own name as the argument.
Solution:
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice") # Prints: Hello, Alice!
In this exercise, you defined a function that takes one argument, and then you called this function with the argument “Alice”. When you run this code, it should print out “Hello, Alice!”. You can call this function with different names, and it will greet each name accordingly.
Python Function Parameters and Arguments
Understanding Parameters and Arguments
In the context of functions, parameters and arguments can be a bit confusing because they can mean different things depending on how they’re used:
- Parameters are the names used when defining a function or a method, and they are placeholders for the values that it will take when called.
- Arguments are the actual values that are passed in when the function is called.
def say_hello(name): # 'name' is a parameter
print(f"Hello, {name}!")
say_hello("Alice") # 'Alice' is an argument
Positional Arguments
Positional arguments are arguments that need to be passed into the function in correct positional order.
def describe_pet(animal_type, pet_name):
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
describe_pet('hamster', 'harry') # 'hamster' and 'harry' are positional arguments
Keyword Arguments
Keyword arguments are arguments passed to a function by explicitly naming each parameter and the corresponding value.
describe_pet(animal_type='hamster', pet_name='harry') # 'animal_type' and 'pet_name' are keyword arguments
Default Arguments
A default argument is a parameter that assumes a default value if a value is not provided in the function call for that parameter.
def describe_pet(pet_name, animal_type='dog'): # 'dog' is a default argument
...
Variable-length Arguments (args and *kwargs)
Sometimes, you might want to define a function that can take any number of arguments, this is achieved by using the special syntax *args and **kwargs in the function signature.
- *args allows you to pass an arbitrary number of positional arguments.
- **kwargs allows you to pass an arbitrary number of keyword arguments.
def my_function(*args, **kwargs):
for arg in args:
print(arg)
for key, value in kwargs.items():
print(f"{key} = {value}")
my_function('Hello', 'World', name='John', age=30)
Practice Exercise: Function with Different Types of Arguments
Let’s create a function that utilizes positional arguments, keyword arguments, and default arguments.
Exercise:
- Define a function named
make_sandwichthat takes in a positional argumentbread_type, a keyword argumenttoasted=False, and an arbitrary number of ingredients as a variable-length argument. - If
toastedis True, print “Toasting the {bread_type} bread.” - Then, print “Adding the following ingredients to your {bread_type} sandwich:” and list out all the ingredients.
Solution:
def make_sandwich(bread_type, *ingredients, toasted=False):
if toasted:
print(f"Toasting the {bread_type} bread.")
print(f"Adding the following ingredients to your {bread_type} sandwich:")
for ingredient in ingredients:
print(ingredient)
make_sandwich('whole grain', 'ham', 'cheese', 'lettuce', toasted=True)
In this exercise, we utilized different types of arguments to make a versatile sandwich-making function.
Return Statement in Python
Understanding the Return Statement
In Python, the return statement is used to send a result back from a function and stop the execution of the function. If the return statement is without any expression, then the special value None is returned.
def add_numbers(a, b):
return a + b # The function returns the result of a + b
result = add_numbers(3, 5) # The return value is stored in the variable 'result'
print(result) # Prints: 8
Returning Single Values
A function in Python can return a single value. This value can be of any data type, including complex types like lists, dictionaries, or even other functions or classes.
def get_full_name(first_name, last_name):
return first_name + " " + last_name # The function returns a string
name = get_full_name("Alice", "Johnson") # The return value is stored in the variable 'name'
print(name) # Prints: Alice Johnson
Returning Multiple Values
A function in Python can return multiple values. These values are usually returned in the form of a tuple, which can then be destructured into multiple variables.
def get_info():
name = "Alice"
age = 25
return name, age # The function returns two values
person_name, person_age = get_info() # The return values are destructured into two variables
print(person_name) # Prints: Alice
print(person_age) # Prints: 25
Practice Exercise: Functions with Return Statements
Let’s practice writing a function that returns both a single value and multiple values.
Exercise:
- Write a function called
calculate_areathat takes in the length and width of a rectangle as arguments, and returns the area. - Write another function called
calculate_dimensionsthat takes in the area and length of a rectangle, and returns both the width and the perimeter.
Solution:
def calculate_area(length, width):
return length * width
def calculate_dimensions(area, length):
width = area / length
perimeter = 2 * (length + width)
return width, perimeter
# Calculate the area of a rectangle with length = 5 and width = 4
area = calculate_area(5, 4)
print(area) # Prints: 20
# Calculate the width and perimeter of a rectangle with area = 20 and length = 5
rect_width, rect_perimeter = calculate_dimensions(area, 5)
print(rect_width) # Prints: 4.0
print(rect_perimeter) # Prints: 18.0
In this exercise, we used the return statement to calculate and return the area, width, and perimeter of a rectangle.
Local and Global Variables in Python
Understanding Local Variables
A variable declared inside the function’s body or in the local scope is known as a local variable. These variables can only be accessed inside the function they are declared in.
def my_function():
local_var = "I'm a local variable"
print(local_var)
my_function() # Prints: I'm a local variable
print(local_var) # Error: local_var is not defined
The variable local_var is a local variable. It’s available from the point it’s declared until the end of the function.
Understanding Global Variables
Global variables are the one that are declared outside of the function or in global scope. This means that a global variable can be accessed inside or outside of the function.
global_var = "I'm a global variable"
def my_function():
print(global_var)
my_function() # Prints: I'm a global variable
print(global_var) # Prints: I'm a global variable
The variable global_var is a global variable. It’s available from the point it’s declared throughout the rest of your program.
Global Keyword
If you want to use a global variable inside a function, but there is a local variable with the same name, you can use the global keyword to indicate the variable is a global variable.
global_var = "I'm a global variable"
def my_function():
global global_var
global_var = "The global variable has been changed"
print(global_var)
my_function() # Prints: The global variable has been changed
print(global_var) # Prints: The global variable has been changed
Practice Exercise: Differentiating Local and Global Variables
Let’s practice differentiating between local and global variables.
Exercise:
- Declare a global variable
xand set it to 10. - Define a function
change_variablesthat declares a local variablexand sets it to 20, and changes the globalxto 30. - Call
change_variablesand then printx.
Solution:
x = 10 # This is a global variable
def change_variables():
x = 20 # This is a local variable
print("Local x inside function:", x)
global x # This refers to the global x
x = 30
change_variables()
print("Global x outside function:", x) # Prints: Global x outside function: 30
In this exercise, you learned the difference between local and global variables, and how to change a global variable from within a function.
Anonymous Functions: Lambda Functions in Python
Introduction to Lambda Functions
In Python, lambda functions are small anonymous functions. They can be used wherever function objects are required. They are syntactically restricted to a single expression. Like def, the lambda keyword creates a function to be called later, but it returns the function instead of assigning it to a name.
Writing Lambda Functions
Lambda functions are written as follows:
lambda arguments: expression
Here is an example of a simple lambda function:
double = lambda x: x * 2
This lambda function takes one argument x and returns x * 2. It’s equivalent to the following regular function:
def double(x):
return x * 2
To call a lambda function, you use the same syntax as a regular function. For example, double(5) would return 10.
Lambda functions can take any number of arguments but can only have one expression. The expression is evaluated and returned, and lambda functions can be used wherever function objects are required.
Practice Exercise: Simple Lambda Functions
Let’s practice writing a lambda function.
Exercise:
- Write a lambda function
powerthat takes two argumentsxandyand returnsxto the power ofy.
Solution:
power = lambda x, y: x ** y
print(power(2, 3)) # Prints: 8
In this exercise, you wrote a lambda function that takes two arguments and used the power operator to calculate x to the power of y.
Python Built-in Functions
Introduction to Python Built-in Functions
Python comes with a set of built-in functions that are readily available for use. These functions provide a base level of functionality for the language and are very powerful tools for different types of tasks. They are universally available, which means you don’t need to import a module to use them.
Commonly Used Built-in Functions
Here are some commonly used built-in functions in Python:
print(): This function prints the specified message to the screen.
print("Hello, World!") # Prints: Hello, World!
input(): This function allows user input.
name = input("Enter your name: ") # Waits for the user to type something and press enter
len(): This function returns the number of items (length) in an object.
print(len("Hello, World!")) # Prints: 13
type(): This function returns the type of an object.
print(type(123)) # Prints: <class 'int'>
str(),int(),float(): These functions convert values to string, integer, or float data type, respectively.
print(str(123)) # Prints: '123'
print(int('123')) # Prints: 123
print(float('123')) # Prints: 123.0
list(),dict(),tuple(),set(): These functions convert values to list, dictionary, tuple, or set data type, respectively.
print(list('123')) # Prints: ['1', '2', '3']
print(dict([(1, 'a'), (2, 'b')])) # Prints: {1: 'a', 2: 'b'}
print(tuple([1, 2, 3])) # Prints: (1, 2, 3)
print(set([1, 2, 2, 3, 3, 3])) # Prints: {1, 2, 3}
Practice Exercise: Exploring Built-in Functions
Let’s put into practice some of the built-in functions we’ve learned.
Exercise:
- Ask the user to input their name and age using the
input()function. - Print the length of their name using the
len()function. - Convert their age to an integer using the
int()function, add one to it, and tell them how old they will be next year.
Solution:
name = input("Enter your name: ")
age = input("Enter your age: ")
print(f"The length of your name is {len(name)} characters.")
next_year_age = int(age) + 1
print(f"Next year you will be {next_year_age} years old.")
In this exercise, you got to practice with input(), len(), and int(), some of Python’s built-in functions.
Function Documentation: Docstrings
Importance of Function Documentation
Documenting your code is a fundamental practice in software development that leads to improved readability and understanding of your code. When it comes to functions in Python, documentation is often provided in the form of docstrings. Docstrings, short for documentation strings, are descriptive text written between triple quotes that explain what a function does.
Single Line and Multi-line Docstrings
In Python, docstrings can be single-line or multi-line.
- Single-line Docstrings: As the name suggests, these are brief descriptions that fit in one line. Single-line docstrings are used for simple functions. They are written like this:
def add(a, b):
"""Adds two numbers together."""
return a + b
- Multi-line Docstrings: These are used for more complex functions that require a more detailed explanation. The first line provides a brief summary, followed by a more comprehensive description. It is also common to include other sections such as
Arguments,Returns, andRaises.
def add(a, b):
"""
Adds two numbers together.
Arguments:
a -- the first number
b -- the second number
Returns: The sum of a and b.
"""
return a + b
Accessing Docstrings
Docstrings can be accessed using the .__doc__ attribute of the function. This can be useful to dynamically access the documentation of a function for reference. Here’s an example:
def add(a, b):
"""Adds two numbers together."""
return a + b
print(add.__doc__) # Prints: Adds two numbers together.
Also, docstrings are used by Python’s help function. You can get the docstring and some other useful info about a function like this:
help(add)
This practice of writing docstrings is very useful for understanding what a function does, especially when you’re working on large codebases or collaborating with other developers. It’s a good habit to write docstrings for your functions, no matter how simple they may seem.
Debugging Functions in Python
Common Errors in Function Definition and Usage
When defining and using functions in Python, you might come across several common errors. Here are a few examples:
- Syntax Error: This occurs when Python’s syntax rules are violated.
def add(a, b) # Missing colon at the end
return a + b
- Indentation Error: Python uses indentation to define blocks of code. Indentation errors occur when this rule is not followed.
def add(a, b):
return a + b # Incorrect indentation
- Name Error: This occurs when a variable is used before it has been defined.
def add(a, b):
return result # result is not defined
print(add(5, 3))
- Type Error: This occurs when an operation is applied to a variable of an inappropriate type.
def add(a, b):
return a + b
print(add(5, "3")) # TypeError because you can't add an integer and a string
Tips to Debug Functions
When encountering an error, there are several steps you can follow to debug your functions:
- Read the Error Message: Python error messages can provide a lot of insight into what went wrong. The error message will typically include the type of error, the line number where the error occurred, and a traceback showing the sequence of function calls leading to the error.
- Print Variable Values: Use
print()statements to display the values of variables at different points in your function. This can help you understand how your variables are changing and where things might be going wrong. - Use a Debugger: Python comes with a built-in debugger called
pdb. This tool allows you to step through your code one line at a time and inspect the values of variables at each step. - Write Test Cases: Write tests for your function to make sure it behaves as expected in different scenarios. This can help you find edge cases that your function doesn’t handle correctly.
- Code Review: Have a fellow programmer review your code. Sometimes a fresh pair of eyes can spot something you might have missed.
Remember that debugging is a skill that improves with practice. The more you code and debug, the better you’ll become at it.
Sure, we will make the project simpler and ensure it only utilizes the material covered this week.
Practice Project
Brief: Develop a Small Python Program Utilizing Learned Function Concepts
For this project, we will create a simple program that performs basic mathematical operations. This will help reinforce your understanding of defining functions, using parameters and return statements.
Requirements:
- Write a function for each of the four basic mathematical operations: addition, subtraction, multiplication, and division.
- Each function should take two parameters (the numbers to operate on) and return the result of the operation.
- Write a fifth function that takes three parameters: the two numbers to operate on, and the operation to perform. This function should call one of the four previous functions based on the operation parameter and return the result.
- Test all the functions and print the results.
Here is a simple example solution:
# Define the four basic mathematical functions
def add(a, b):
"""Adds two numbers."""
return a + b
def subtract(a, b):
"""Subtracts the second number from the first."""
return a - b
def multiply(a, b):
"""Multiplies two numbers."""
return a * b
def divide(a, b):
"""Divides the first number by the second. Returns None if division by zero."""
return a / b if b != 0 else None
# Define a function that takes the two numbers and an operation to perform
def calculate(a, b, operation):
"""Performs the given operation on two numbers."""
if operation == "add":
return add(a, b)
elif operation == "subtract":
return subtract(a, b)
elif operation == "multiply":
return multiply(a, b)
elif operation == "divide":
return divide(a, b)
else:
return None
# Test the functions
print(add(5, 3)) # 8
print(subtract(5, 3)) # 2
print(multiply(5, 3)) # 15
print(divide(5, 3)) # 1.6666666666666667
print(calculate(5, 3, "add")) # 8
print(calculate(5, 3, "subtract")) # 2
print(calculate(5, 3, "multiply")) # 15
print(calculate(5, 3, "divide")) # 1.6666666666666667
This program demonstrates how to define functions, use parameters and return values, and call functions from other functions. As you continue learning Python, you’ll be able to create much more complex and interesting programs.
Summary and Next Steps
Recap of Functions in Python
Today, you’ve learned about the foundational aspect of Python programming: Functions. We discussed what functions are, why they are useful, and how to define and call them. We explored different types of function parameters, the return statement, local and global variables, and lambda (anonymous) functions. We also covered Python’s built-in functions, documenting functions using docstrings, and common tips for debugging functions. Finally, you got to practice these concepts by creating a simple math operation program.
Preview of Next Day’s Lesson: Introduction to Python’s Data Structures
In the next lesson, we will dive into an important aspect of Python: Data Structures. You’ll learn about the four built-in data structures in Python: Lists, Tuples, Dictionaries, and Sets. We’ll discuss how they are used, their characteristics, and their advantages and disadvantages. Understanding these data structures is essential to solve a wide range of problems when programming in Python.
Self-Study Resources and Reading Recommendations
- Python.org Official Documentation – Here you can find the official Python documentation on functions.
- Learn Python the Hard Way – This book by Zed Shaw is a great resource for beginners. It takes a hands-on approach to teaching Python and covers functions in detail.
- Automate the Boring Stuff with Python – This book by Al Sweigart is perfect for beginners and it’s a lot of fun. It teaches Python programming by guiding you through projects to automate tasks on your computer.
- Codecademy’s Python Course – This interactive course has a great module on functions.
- Real Python – This website has many great tutorials and articles about all aspects of Python programming, including functions.
Remember, the key to learning programming is practice. Try to spend some time each day coding, even if it’s only for a little bit. Happy coding!