Week 8: Functions - The Power of Reusability

Learn how to define and use functions to write more organized and efficient Python code.

Explore Chapter 8

Chapter 8: Writing Reusable Code with Functions

Defining Functions using `def`.

Functions are blocks of organized, reusable code that perform a specific task. They allow you to break down your program into smaller, more manageable parts, making it easier to write, read, and maintain. Functions also promote code reusability, as you can call the same function multiple times from different parts of your program.

Syntax

def function_name(parameters):
    # Code to be executed inside the function
    statement1
    statement2
    # ...
    return result  # Optional return statement
  • The `def` keyword is used to define a function.
  • `function_name` is the name you give to your function. It should be descriptive and follow the snake_case convention (e.g., `calculate_area`, `greet_user`).
  • `parameters` are optional input values that the function can receive. They are enclosed in parentheses `()`. A function can have zero or more parameters.
  • The colon `:` marks the beginning of the function's code block.
  • The indented code block contains the statements that are executed when the function is called.
  • The `return` statement is optional. It allows the function to send a value back to the caller.

Example: A Simple Greeting Function

def greet(name):
    print("Hello,", name + "!")

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

Function Parameters and Arguments.

Parameters are the variables listed inside the parentheses in the function definition. Arguments are the actual values that are passed to the function when it is called.

Positional Arguments

When you call a function with positional arguments, the arguments are passed to the parameters in the order they are defined.

def describe_person(name, age, city):
    print("Name:", name)
    print("Age:", age)
    print("City:", city)

describe_person("Alice", 30, "New York")
# "Alice" is passed to name, 30 to age, and "New York" to city

Keyword Arguments

You can also call a function using keyword arguments, where you explicitly specify the parameter name along with the value. This allows you to pass arguments in any order.

describe_person(age=25, city="London", name="Bob")
# Arguments are passed based on the keyword, not the order

Default Parameter Values

You can provide default values for parameters in the function definition. If the caller does not provide a value for that parameter, the default value is used.

def greet(name="Guest"):
    print("Hello,", name + "!")

greet()        # Output: Hello, Guest! (uses default value)
greet("Charlie") # Output: Hello, Charlie!

Variable-Length Arguments (`*args` and `**kwargs`)

  • `*args`: Allows you to pass a variable number of non-keyword arguments to a function. They are collected into a tuple.
  • `**kwargs`: Allows you to pass a variable number of keyword arguments to a function. They are collected into a dictionary.
def print_info(*args, **kwargs):
    print("Positional arguments:", args)
    print("Keyword arguments:", kwargs)

print_info(1, 2, 3, name="Alice", age=30)
# Output:
# Positional arguments: (1, 2, 3)
# Keyword arguments: {'name': 'Alice', 'age': 30}

Returning Values from Functions.

The `return` statement is used to send a value back from the function to the caller. A function can return any data type (e.g., a number, a string, a list, a tuple, a dictionary, or even another function).

Basic Return

def add(x, y):
    return x + y

result = add(5, 3)  # result will be 8
print(result)

Returning Multiple Values

Python functions can effectively return multiple values by returning them as a tuple.

def calculate_area_and_perimeter(length, width):
    area = length * width
    perimeter = 2 * (length + width)
    return area, perimeter

area, perimeter = calculate_area_and_perimeter(10, 5)
print("Area:", area)
print("Perimeter:", perimeter)

`None` Return

If a function does not explicitly include a `return` statement, or if the `return` statement is used without any value, the function implicitly returns `None`. `None` is a special value in Python that represents the absence of a value.

def print_message(message):
    print(message)

return_value = print_message("Hello!")
print("Return value:", return_value) # Output: Return value: None

Scope of Variables (Local vs. Global).

The scope of a variable refers to the region of the program where that variable can be accessed. Python has two main types of variable scope: local and global.

Local Variables

A local variable is a variable that is defined inside a function. It is only accessible within that function. Local variables are created when the function is called and destroyed when the function returns.

def my_function():
    local_variable = 10
    print("Inside function:", local_variable)

my_function()
# print(local_variable)  # This would raise a NameError because local_variable is not accessible here

Global Variables

A global variable is a variable that is defined outside of any function. It is accessible from anywhere in the program, including inside functions. However, it's generally best practice to minimize the use of global variables, as they can make your code harder to understand and debug.

global_variable = 20

def another_function():
    print("Inside function:", global_variable)

another_function()
print("Outside function:", global_variable)

def modify_global():
    global global_variable  # Use the 'global' keyword to modify the global variable
    global_variable = 30

modify_global()
print("After modification:", global_variable)

The `global` Keyword

To modify a global variable from within a function, you need to use the `global` keyword. This tells Python that you want to work with the global variable, not create a new local variable with the same name.

Understanding variable scope is crucial to avoid unintended side effects and write clean, maintainable code.

Syllabus