Functions are a fundamental aspect of programming that allows for modular, reusable, and organized code. In Python, functions enable you to encapsulate code into blocks that can be executed multiple times, with various inputs and can return values. This section will cover defining functions, calling them, arguments, return values, scope, and some advanced features such as lambda functions and decorators.
Defining Functions
In Python, a function is defined using the def keyword, followed by the function name, parentheses containing any parameters, and a colon. The function body is indented.

def greet():
print("Hello, world!")
In this example, greet is a function that prints “Hello, world!” when called.
Calling Functions
To execute a function, you call it by its name followed by parentheses.
greet() # Output: Hello, world!
Parameters and Arguments
Functions can accept parameters, allowing them to process different inputs.
Positional Arguments
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # Output: Hello, Alice!
In this example, name is a parameter, and "Alice" is an argument.
Default Arguments
You can provide default values for parameters, which are used if no argument is provided.
def greet(name="world"):
print(f"Hello, {name}!")
greet() # Output: Hello, world!
greet("Alice") # Output: Hello, Alice!
Keyword Arguments
You can pass arguments by name, allowing you to specify them in any order.
def greet(first_name, last_name):
print(f"Hello, {first_name} {last_name}!")
greet(last_name="Smith", first_name="John") # Output: Hello, John Smith!
Arbitrary Arguments
You can use *args to accept a variable number of positional arguments and **kwargs for keyword arguments.
def greet(*names):
for name in names:
print(f"Hello, {name}!")
greet("Alice", "Bob", "Charlie")
# Output:
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!
def greet(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
greet(first_name="John", last_name="Doe")
# Output:
# first_name: John
# last_name: Doe
Return Values
Functions can return values using the return statement.
def add(a, b):
return a + b
result = add(2, 3)
print(result) # Output: 5
A function can return multiple values as a tuple.
def add_and_subtract(a, b):
return a + b, a - b
sum_result, diff_result = add_and_subtract(5, 3)
print(sum_result) # Output: 8
print(diff_result) # Output: 2
Scope and Lifetime of Variables
Local Scope
Variables defined inside a function are local to that function and cannot be accessed outside of it.
def my_function():
local_var = 10
print(local_var)
my_function() # Output: 10
# print(local_var) # This will raise a NameError
Global Scope
Variables defined outside all functions are global and can be accessed anywhere in the code. To modify a global variable inside a function, use the global keyword.
global_var = 10
def my_function():
global global_var
global_var = 20
my_function()
print(global_var) # Output: 20
Nonlocal Scope
The nonlocal keyword is used to work with variables inside nested functions, allowing you to modify a variable in the nearest enclosing scope that is not global.
def outer_function():
x = "local"
def inner_function():
nonlocal x
x = "nonlocal"
print("Inner:", x)
inner_function()
print("Outer:", x)
outer_function()
# Output:
# Inner: nonlocal
# Outer: nonlocal
Advanced Features
Lambda Functions
Lambda functions are small anonymous functions defined using the lambda keyword. They can have any number of arguments but only one expression.
add = lambda a, b: a + b
print(add(2, 3)) # Output: 5
# Example with map
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # Output: [1, 4, 9, 16, 25]
Higher-Order Functions
Functions can take other functions as arguments or return them, enabling powerful patterns like map, filter, and reduce.
def apply_function(func, value):
return func(value)
result = apply_function(lambda x: x ** 2, 5)
print(result) # Output: 25
Decorators
Decorators are a way to modify or enhance functions without changing their code. They are applied using the @decorator syntax.
def decorator_function(original_function):
def wrapper_function():
print("Wrapper executed before", original_function.__name__)
return original_function()
return wrapper_function
@decorator_function
def say_hello():
print("Hello!")
say_hello()
# Output:
# Wrapper executed before say_hello
# Hello!
Docstrings
Docstrings are string literals that appear right after the definition of a function (or class, module, etc.) and are used to document the function.
def greet(name):
"""
This function greets the person whose name is passed as an argument.
"""
print(f"Hello, {name}!")
print(greet.__doc__)
# Output: This function greets the person whose name is passed as an argument.
Conclusion
Functions are a cornerstone of Python programming, providing a way to encapsulate code for reuse, readability, and modularity. By understanding how to define functions, pass arguments, return values, manage scope, and use advanced features like lambda functions and decorators, you can write more efficient and maintainable Python code. Functions allow you to abstract and organize your code effectively, making it easier to develop complex applications.
Discover more from Learn with Anu Arora
Subscribe to get the latest posts sent to your email.
