Functions in Python: Organizing Code for Reusability
Functions are organized, reusable blocks of code used to perform a single or related function. Functions improve the modularity of an application and promote code reuse. As you already know, Python provides many built-in functions, such as print()
. However, you can also create your own functions, which are called user-defined functions.
Defining a Function
You can define a function with any desired functionality by following these simple rules:
The function block starts with the
def
keyword, followed by the function name and parentheses()
.Any input parameters or arguments must be placed within the parentheses. You can define parameters within the parentheses.
The first statement in the function can optionally be a documentation string (docstring), used to describe the function.
The function content starts with a colon
:
and is indented.A
return [expression]
statement ends the function, optionally returning a value to the caller. If there is no expression, the function returnsNone
.
Syntax
Python defines functions using the def
keyword, and the general format is as follows:
def function_name(parameters): function_body
By default, the parameter values and parameter names are matched in the order they are declared.
Example
Let’s use a simple function to output "Hello World!":
#!/usr/bin/python3 def hello(): print("Hello World!") hello()
More Complex Example: Function with Parameters
Example (Python 3.0+)
This function compares two numbers and returns the larger one:
#!/usr/bin/python3 def max(a, b): if a > b: return a else: return b a = 4 b = 5 print(max(a, b))
Output:
5
Example: Function to Calculate Area
#!/usr/bin/python3 # Function to calculate area def area(width, height): return width * height def print_welcome(name): print("Welcome", name) print_welcome("Runoob") w = 4 h = 5 print("width =", w, " height =", h, " area =", area(w, h))
Output:
Welcome Runoob width = 4 height = 5 area = 20
Function Calls
Defining a function assigns it a name, specifies the parameters, and creates the code block structure. Once this is done, you can call the function from another function or directly from the Python prompt.
Here’s an example of calling the printme()
function:
Example (Python 3.0+):
#!/usr/bin/python3 # Define the function def printme(str): # Print any string passed in print(str) return # Call the function printme("I am calling a user-defined function!") printme("Calling the same function again")
Output:
I am calling a user-defined function! Calling the same function again
Argument Passing
In Python, types belong to objects, not to variables. Variables don’t have types; they are merely references to objects.
a = [1, 2, 3] a = "Runoob"
In the code above, [1, 2, 3]
is a list, and "Runoob"
is a string, but a
is just a reference to these objects. It can reference any type of object.
Mutable and Immutable Objects in Python
In Python, strings
, tuples
, and numbers
are immutable objects, whereas lists
, dictionaries
, and other collections are mutable.
Immutable Types:
For example, when you assign a = 5
and later assign a = 10
, Python creates a new integer object 10
and assigns it to a
. The original integer 5
is discarded. This process doesn’t change the value of a
; rather, a new object is created and assigned.
Mutable Types:
When you assign la = [1, 2, 3, 4]
and then update la[2] = 5
, it changes the third element of the list. The list la
itself remains the same, but a part of its content has been modified.
Argument Passing in Python Functions:
Immutable Types: Similar to pass-by-value in C++, such as integers, strings, and tuples. For instance, in
fun(a)
, the value ofa
is passed, and any changes withinfun(a)
will not affect the originala
object. Instead, a new object is created.Mutable Types: Similar to pass-by-reference in C++, such as lists and dictionaries. In
fun(la)
, the actual listla
is passed, and modifications within the function will affect the list outside the function as well.
In Python, everything is an object. Technically, we can’t say whether Python uses pass-by-value or pass-by-reference; instead, we talk about passing immutable objects or mutable objects.
Example: Passing Immutable Objects
Use the id()
function to check how memory addresses change.
Example (Python 3.0+):
def change(a): print(id(a)) # Points to the same object a = 10 print(id(a)) # Now points to a new object a = 1 print(id(a)) change(a)
Output:
4379369136 4379369136 4379369424
This shows that the function parameter and the original argument point to the same object initially (same id
). However, after modifying the parameter inside the function, it points to a different object.
Example: Passing Mutable Objects
If a mutable object is modified inside a function, the changes affect the original object as well.
Example (Python 3.0+):
#!/usr/bin/python3 # Function to modify a list def changeme(mylist): "Modifies the passed list" mylist.append([1, 2, 3, 4]) print("Values inside the function: ", mylist) return # Calling changeme function mylist = [10, 20, 30] changeme(mylist) print("Values outside the function: ", mylist)
Output:
Values inside the function: [10, 20, 30, [1, 2, 3, 4]] Values outside the function: [10, 20, 30, [1, 2, 3, 4]]
The object passed to the function and the modified object outside the function share the same reference, leading to the same changes.
Parameters
When calling functions in Python, there are different types of formal parameters:
Required Parameters
Keyword Parameters
Default Parameters
Variable-length Parameters
Required Parameters:
Required parameters must be passed in the correct order. The number of arguments in the function call must match the function’s definition.
If you call printme()
without passing an argument, it results in a syntax error:
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printme(str): "Prints any passed string" print(str) return # Calling the function without an argument will raise an error printme()
Output:
Traceback (most recent call last): File "test.py", line 10, in <module> printme() TypeError: printme() missing 1 required positional argument: 'str'
Keyword Arguments:
Keyword arguments are closely tied to function calls. Using keyword arguments allows us to pass values to functions in a way that does not depend on the order of parameters, as long as the parameter names are provided.
This example uses keyword arguments to call the printme()
function:
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printme(str): "Prints any passed string" print(str) return # Calling printme using keyword arguments printme(str = "Runoob Tutorial")
Output:
Runoob Tutorial
Example: Parameters Without Specified Order
You don’t need to follow the order of parameters when using keyword arguments.
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printinfo(name, age): "Prints the provided information" print("Name: ", name) print("Age: ", age) return # Calling printinfo with parameters out of order printinfo(age=50, name="Runoob")
Output:
Name: Runoob Age: 50
Default Parameters
When calling a function, if no argument is passed, the function will use the default parameter. In the following example, if the age
parameter is not provided, the function will use the default value:
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printinfo(name, age=35): "Prints any passed information" print("Name: ", name) print("Age: ", age) return # Calling the printinfo function printinfo(age=50, name="runoob") print("------------------------") printinfo(name="runoob")
Output:
Name: runoob Age: 50 ------------------------ Name: runoob Age: 35
Variable-length Arguments
Sometimes, you may need a function that can handle more arguments than you initially declared. These are called variable-length arguments, and unlike the previous two types, they are not named in the function definition. The basic syntax is as follows:
def functionname([formal_args,] *var_args_tuple): "Function docstring" function_suite return [expression]
The parameter prefixed with an asterisk *
will be a tuple, containing all the unnamed variable arguments.
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printinfo(arg1, *vartuple): "Prints any passed arguments" print("Output: ") print(arg1) print(vartuple) # Calling the printinfo function printinfo(70, 60, 50)
Output:
Output: 70 (60, 50)
If no additional arguments are passed during the function call, the variable is an empty tuple. You can also choose not to pass any unnamed arguments to the function. Here’s an example:
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printinfo(arg1, *vartuple): "Prints any passed arguments" print("Output: ") print(arg1) for var in vartuple: print(var) return # Calling the printinfo function printinfo(10) printinfo(70, 60, 50)
Output:
Output: 10 Output: 70 60 50
Double Asterisk **
in Function Parameters
You can also pass a variable-length argument dictionary using two asterisks **
. The basic syntax is:
def functionname([formal_args,] **var_args_dict): "Function docstring" function_suite return [expression]
Arguments prefixed with two asterisks **
are treated as a dictionary of key-value pairs.
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def printinfo(arg1, **vardict): "Prints any passed arguments" print("Output: ") print(arg1) print(vardict) # Calling the printinfo function printinfo(1, a=2, b=3)
Output:
Output: 1 {'a': 2, 'b': 3}
Single Asterisk *
in Function Parameters
When a single asterisk *
appears in a function’s parameter list, the parameters following the *
must be passed as keyword arguments.
Example:
def f(a, b, *, c): return a + b + c
When calling this function, the argument for c
must be passed using a keyword, as shown below:
>>> f(1, 2, 3) # Error Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() takes 2 positional arguments but 3 were given >>> f(1, 2, c=3) # Correct 6
Anonymous Functions
In Python, anonymous functions are created using the lambda
keyword.
An anonymous function means that it is defined without using the def
keyword. Instead, lambda
expressions are used, which are much simpler than standard function definitions. The body of a lambda
function consists of a single expression, not a block of code. It can encapsulate limited logic within the expression itself.
A
lambda
function has its own namespace and can only access parameters passed to it or variables in its local scope.Although
lambda
functions are written in one line, they are not the same as C or C++ inline functions, which are designed to avoid stack memory usage and improve execution speed for small functions.
Syntax
The syntax of a lambda
function consists of a single statement:
lambda [arg1 [, arg2, ... argn]]: expression
Here's an example that adds 10 to the argument a
:
Example:
x = lambda a : a + 10 print(x(5))
Output:
15
Here’s another example of a lambda
function that takes two parameters:
Example (Python 3.0+):
#!/usr/bin/python3 # Defining a lambda function sum = lambda arg1, arg2: arg1 + arg2 # Calling the sum function print("The sum is: ", sum(10, 20)) print("The sum is: ", sum(20, 20))
Output:
The sum is: 30 The sum is: 40
Encapsulating a Lambda in Another Function
You can encapsulate a lambda
function inside another function to create multiple anonymous functions with similar logic. Here’s an example where a lambda
function is wrapped inside myfunc
, and different instances are created by passing different arguments.
Example:
def myfunc(n): return lambda a : a * n mydoubler = myfunc(2) mytripler = myfunc(3) print(mydoubler(11)) print(mytripler(11))
Output:
22 33
For more on anonymous functions, you can refer to: Python Lambda Functions.
return
Statement
The return [expression]
statement is used to exit a function and optionally pass an expression back to the caller. A return
statement without any arguments returns None
. In previous examples, we didn’t show how to return values, so here’s an example illustrating the use of return
.
Example (Python 3.0+):
#!/usr/bin/python3 # Function definition def sum(arg1, arg2): "Returns the sum of two arguments." total = arg1 + arg2 print("Inside the function: ", total) return total # Calling the sum function total = sum(10, 20) print("Outside the function: ", total)
Output:
Inside the function: 30 Outside the function: 30
Positional-only Parameters
Starting with Python 3.8, a new syntax /
was introduced to specify that certain function parameters must be passed as positional arguments and cannot be passed as keyword arguments.
In the example below, the parameters a
and b
must be positional, while c
and d
can be either positional or keyword arguments, and e
and f
must be keyword arguments:
def f(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f)
The following method calls are valid:
f(10, 20, 30, d=40, e=50, f=60)
But the following calls will raise an error:
f(10, b=20, c=30, d=40, e=50, f=60) # 'b' cannot be used as a keyword argument f(10, 20, 30, 40, 50, f=60) # 'e' must be passed as a keyword argument