Python Functions

Python Tutorial

Table of Contents

Python Functions: A Beginner-Friendly Practical Guide

Python Functions: A Beginner-Friendly Practical Guide

Welcome to your hands-on guide to Python functions! This tutorial is designed for beginners and covers everything you need to know to start writing, using, and mastering functions in Python. You’ll learn the basics, explore advanced features like decorators and generators, and discover practical tips and common mistakes to avoid. Let’s get started!

Learning Goals

  • Understand what functions are and why they matter in Python
  • Learn how to define, call, and use functions effectively
  • Master function arguments, return values, and variable scope
  • Explore advanced topics: lambda functions, decorators, recursion, and generators
  • Apply best practices and avoid common mistakes

What is a Function?

A function is a block of code that runs only when you call it. Functions help you organize your code, avoid repetition, and make your programs easier to read and maintain. You can pass data to functions (arguments), and they can return data as a result.

Why Use Functions?

  • Reduce code repetition
  • Make code easier to test and debug
  • Improve readability and structure
  • Enable code reuse

Defining and Calling Functions

To define a function in Python, use the def keyword, followed by the function name and parentheses. The code inside the function must be indented.

def greet():
    print("Hello from a function!")

greet()  # Calling the function

Output:
Hello from a function!

Function Naming Rules

  • Start with a letter or underscore (_)
  • Can contain letters, numbers, and underscores
  • Case-sensitive (e.g., myFunction and myfunction are different)
  • Use descriptive names (e.g., calculate_sum)

Function Arguments and Parameters

Arguments are values you pass to a function. Parameters are the variables listed in the function definition.

def add(a, b):
    return a + b

result = add(2, 3)
print(result)  # Output: 5
TermDescription
ParameterVariable in the function definition
ArgumentValue passed to the function when called

Default Parameter Values

You can assign default values to parameters. If the function is called without that argument, the default value is used.

def greet(name="friend"):
    print("Hello", name)

greet("Alice")
greet()  # Uses default value

Output:
Hello Alice
Hello friend

Keyword Arguments

Pass arguments using key=value syntax. The order does not matter.

def describe_pet(animal, name):
    print(f"I have a {animal} named {name}.")

describe_pet(name="Buddy", animal="dog")

Positional Arguments

Arguments passed without keywords are positional. Their order must match the function definition.

def describe_pet(animal, name):
    print(f"I have a {animal} named {name}.")

describe_pet("dog", "Buddy")

Mixing Positional and Keyword Arguments

Positional arguments must come before keyword arguments.

def describe_pet(animal, name, age):
    print(f"I have a {age}-year-old {animal} named {name}.")

describe_pet("dog", name="Buddy", age=5)

Arbitrary Arguments: *args and **kwargs

Use *args to accept any number of positional arguments (as a tuple), and **kwargs for any number of keyword arguments (as a dictionary).

def print_names(*names):
    for name in names:
        print(name)

print_names("Alice", "Bob", "Charlie")
def print_info(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=30, city="Paris")

Unpacking Arguments

You can use * and ** to unpack lists/tuples and dictionaries into function arguments.

def add(a, b, c):
    return a + b + c

nums = [1, 2, 3]
print(add(*nums))  # Output: 6
def greet(first, last):
    print(f"Hello {first} {last}")

person = {"first": "Alice", "last": "Smith"}
greet(**person)

Return Values

Functions can return values using the return statement. If no return is specified, the function returns None by default.

def get_greeting():
    return "Hello from a function"

message = get_greeting()
print(message)

Variable Scope in Python

The scope of a variable determines where it can be accessed in your code.

ScopeDescriptionExample
LocalDeclared inside a function; accessible only theredef f(): x = 1
GlobalDeclared outside any function; accessible everywherex = 1
NonlocalUsed in nested functions to refer to variables in the nearest enclosing scopenonlocal x
x = "global"
def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print("Inner:", x)
    inner()
    print("Outer:", x)
outer()
print("Global:", x)

The global and nonlocal Keywords

  • global: Use inside a function to modify a global variable.
  • nonlocal: Use in a nested function to modify a variable in the enclosing (outer) function.

Lambda (Anonymous) Functions

A lambda function is a small, anonymous function defined with the lambda keyword. It can have any number of arguments but only one expression.

add_ten = lambda x: x + 10
print(add_ten(5))  # Output: 15
sum_three = lambda a, b, c: a + b + c
print(sum_three(1, 2, 3))  # Output: 6

Lambda functions are often used with map(), filter(), and sorted() for concise, custom behavior.

numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)  # Output: [2, 4, 6, 8, 10]

Recursion

Recursion is when a function calls itself to solve a problem. Every recursive function must have a base case to stop the recursion.

def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))  # Output: 120
Warning: Recursive functions can cause a stack overflow if the base case is missing or not reached.

Decorators

A decorator is a function that takes another function as input and returns a new function with added behavior. Decorators are applied using the @decorator_name syntax.

def changecase(func):
    def wrapper():
        return func().upper()
    return wrapper

@changecase
def greet():
    return "Hello Sally"

print(greet())  # Output: HELLO SALLY

To handle functions with arguments, use *args and **kwargs in your decorator’s wrapper function.

def changecase(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs).upper()
    return wrapper

@changecase
def greet(name):
    return f"Hello {name}"

print(greet("John"))  # Output: HELLO JOHN
Tip: Use functools.wraps to preserve the original function’s metadata (like __name__ and __doc__) when writing decorators.

Generators

Generators are special functions that can pause and resume their execution, producing a sequence of values over time. They use the yield keyword instead of return.

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

for num in count_up_to(5):
    print(num)

Generators are memory-efficient because they generate values on-the-fly, making them ideal for working with large datasets.

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

gen = fibonacci()
for _ in range(10):
    print(next(gen))

Generator Expressions

Generator expressions are like list comprehensions but use parentheses and produce values one at a time.

gen_exp = (x * x for x in range(5))
print(list(gen_exp))  # Output: [0, 1, 4, 9, 16]

Common Mistakes and Practical Tips

MistakeWhat HappensHow to Fix
Missing returnFunction returns NoneAdd a return statement
Wrong argument orderUnexpected results or errorsUse keyword arguments or check order
Modifying global variable without globalUnboundLocalErrorUse global keyword
Infinite recursionRecursionErrorAlways define a base case
Using return instead of yield in generatorsGenerator stops after first valueUse yield for multiple values

Summary and Next Steps

  • Functions are essential for organizing and reusing code in Python.
  • Understand arguments, return values, and scope for effective function use.
  • Explore advanced features like lambda functions, decorators, recursion, and generators for more powerful code.
  • Practice writing your own functions and experiment with the examples above.

Ready to go further? Try building small projects, explore Python's standard library, and check out more advanced topics like object-oriented programming and modules on skillplayground!

Practice Challenge

Write a function that takes any number of numbers and returns their sum. Then, write a generator that yields the Fibonacci sequence up to a given number.

Keep Learning

  • Practice with exercises and challenges on skillplayground
  • Explore Python's built-in functions and modules
  • Learn about object-oriented programming, file handling, and more

Tutorial created by skillplayground. Happy coding!

Scroll to Top