Functions
Function = reusable blocks of code that perform specific tasks. They help organize code, avoid repetition, and make programs easier to understand.
In Python functions, the terms parameter and argument are often used interchangeably, but they have distinct meanings:
- Parameter is the variable name listed in the function definition (the placeholder).
- Argument is the actual value you pass to the function when you call it.
Parameters & Arguments
def greet(name): # 'name' is a parameter
print(f"Hello, {name}!")
greet("Alice") # "Alice" is an argument
Here:
nameis the parameter."Alice"is the argument.
In short: parameters are the blueprint; arguments are the materials you give to follow that blueprint.
Defining a simple function
def greet(name):
"""This function greets the person passed as parameter"""
print(f"Hello, {name}!")
# Calling the function
greet("Alice") # Output: Hello, Alice!
Function with return value
def square(number):
"""Returns the square of a number"""
return number * number
result = square(5)
print(result) # Output: 25
Function with multiple parameters
def add_numbers(a, b):
"""Adds two numbers and returns the result"""
return a + b
sum_result = add_numbers(3, 7)
print(sum_result) # Output: 10
Function with default arguments
def power(base, exponent=2):
"""Raises base to the power of exponent (default is 2)"""
return base ** exponent
print(power(3)) # Output: 9 (uses default exponent)
print(power(3, 3)) # Output: 27
Variable-length arguments (*args)
Variable-length arguments (*args) = *args allows a function to accept any number of positional arguments. The arguments are packed into a tuple inside the function.
def average(*numbers):
"""Calculates average of any number of values"""
return sum(numbers) / len(numbers)
print(average(1, 2, 3)) # Output: 2.0
print(average(10, 20, 30, 40)) # Output: 25.0
def add(*numbers):
total = 0
for number in numbers:
total += number
return total
print(add(10, 10, 10, 10, 10, 10, 10, 10, 10, 10))
Keyword arguments (**kwargs)
Keyword arguments (**kwargs) = **kwargs allows a function to accept any number of keyword arguments. The arguments are packed into a dictionary inside the function.
def person_info(**details):
"""Prints person information from keyword arguments"""
for key, value in details.items():
print(f"{key}: {value}")
person_info(name="John", age=30, city="New York")
# Output:
# name: John
# age: 30
# city: New York
Lambda functions
Lambda functions are small, anonymous functions defined using the lambda keyword. They can have any number of arguments but only one expression. The expression is evaluated and returned.
Syntax
lambda– keywordarguments– comma-separated list of parametersexpression– a single Python expression (cannot contain statements likereturn,if-elsecan be used as a conditional expression though)
multiply = lambda x, y: x * y
print(multiply(4, 5)) # Output: 20
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # Output: [1, 4, 9, 16, 25]
Often used with map(), filter(), reduce() & sorted
Common use cases
1. With map() – apply function to every item
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # Output: [1, 4, 9, 16, 25]
names = ["alice", "bob", "charlie"]
upper_names = list(map(lambda name: name.upper(), names))
print(upper_names) # Output: ['ALICE', 'BOB', 'CHARLIE']
2. With filter() – keep items that satisfy a condition
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # Output: [2, 4, 6, 8]
words = ["hi", "hello", "hey", "greetings"]
long_words = list(filter(lambda w: len(w) > 3, words))
print(long_words) # Output: ['hello', 'greetings']
3. With sorted() – custom sorting key
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78}
]
sorted_by_grade = sorted(students, key=lambda student: student["grade"])
print(sorted_by_grade)
# Output:
# [{'name': 'Charlie', 'grade': 78}, {'name': 'Alice', 'grade': 85}, {'name': 'Bob', 'grade': 92}]
names = ["Alice", "Bob", "Christopher"]
sorted_names = sorted(names, key=lambda name: len(name))
print(sorted_names) # Output: ['Bob', 'Alice', 'Christopher']
4. With reduce() – cumulative operation (from functools)
from functools import reduce
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product) # Output: 24 (1*2*3*4)
Recursive function
A recursive function is a function that calls itself in order to solve a problem. Recursion is a technique where the solution to a problem depends on solving smaller instances of the same problem.
def factorial(n):
"""Calculates factorial recursively"""
if n == 1:
return 1
else:
return n * factorial(n-1)
print(factorial(5)) # Output: 120
Function annotations (type hints)
def circle_area(radius: float) -> float:
"""Calculates area of circle with type hints"""
return 3.14159 * radius ** 2
print(circle_area(2.5)) # Output: 19.6349375
Scope of variables
global_var = "I'm global"
def scope_demo():
local_var = "I'm local"
print(local_var) # Can access local variable
print(global_var) # Can access global variable
scope_demo()
# print(local_var) # Would cause error - local_var not defined outside function
Function docstrings
def documented_function():
"""This is a docstring.
It can span multiple lines and explain:
- What the function does
- What parameters it takes
- What it returns
"""
return "This function is well-documented"
# Accessing the docstring
print(documented_function.__doc__)