
How to Create a Function in Python
In this lesson of the Python course, I will explain how to create a function in the Python language.
What is a function? It is a block of code that performs a specific task and can be called multiple times within the main program. It allows you to have a more organized, compact, and easy-to-read program.
In Python, functions are defined using the keyword "def."
def function_name(arguments):
# function code
return return_value
The code inside a function doesn't run when the function is defined; it only runs when the function is called.
The function has the following characteristics:
- The function must have a unique name.
- It can accept input arguments in parentheses that it uses during the execution of the code block.
- The code inside the function must be indented to the right of the function definition.
- The function returns a return value using the return statement.
Note. The function can also receive no input arguments. In this case, you still need to indicate the parentheses after the name. Additionally, the function may also not return anything as a return value. Therefore, the return statement can be omitted. For example, you can use the function simply to print something on the screen.
Example
Here is a practical example
Define a function that accepts two input values and assigns them to local variables a and b.
- # function definition
- def sum(a,b):
- result=a+b
- return result
The function sums the two values a and b and assigns the sum to the result variable.
Finally, it returns the result to the calling program.
Next, add a call to the sum() function in which you pass the values 2 and 3.
- # function definition
- def sum(a,b):
- result=a+b
- return result
- # first call
- s = sum(2,3)
- print(s)
When you run the program, the sum() function is called with the arguments a=2 and b=3, returning 5 as a result.
Therefore, the main program prints the result on the screen
5
Now add another call to the function in which you pass the values a=4 and b=5.
- # function definition
- def sum(a,b):
- result=a+b
- return result
- # first call
- s = sum(2,3)
- print(s)
- # second call
- s = sum(4,5)
- print(s)
In this case, the function is called twice.
- In the first call sum(2, 3), the function returns 5.
- In the second call sum(4, 5), the function returns 9.
Therefore, the output of the program is:
5
9
Using functions allows you to write the code once and call it only when you need it.
This way, you avoid writing it multiple times.
Note. If you want to modify the program code in the future, such as to calculate the difference instead of the sum, you only need to modify the function once.
Function Parameters
In Python, function parameters are the variables defined within the parentheses of a function's declaration. They play a crucial role in feeding values to the function.
- def sum(a, b):
- print(a + b)
- c = sum(2, 3)
Take, for example, the labels "a" and "b" in this case; they represent the function's parameters. When we pass 2 and 3 to the function, these values are known as arguments.
The complete set of parameters, in our case (a, b), is referred to as the function's signature.
Parameters are generally passed by their position in the signature, from left to right. This process, where parameters are matched with their corresponding arguments, is termed matching.
For instance, in a function call, the first value (2) is assigned to the first parameter (a), and so on. This is known as positional matching.
- def sum(a, b):
- print(a + b)
- c = sum(2, 3)
Alternatively, parameters can also be passed by their names rather than by their positions, known as keyword matching.
- def sum(a, b):
- print(a + b)
- c = sum(b=3, a=2)
It's important that the function's parameter count aligns with the number of arguments provided, regardless of the matching method.
Parameters can be passed in a hybrid fashion, too: some by position, others by keyword. However, remember to always place positional parameters before keyword parameters.
- def sum(a, b):
- print(a + b)
- c = sum(2, b=3)
Python also facilitates specifying default values for parameters. These defaults are utilized when no explicit value is provided for a parameter.
However, ensure that parameters with default values are listed after non-default ones.
- def sum(a, b=0):
- print(a + b)
- c = sum(2)
For situations where the number of parameters is uncertain, Python's *args can be used to capture any excess positional parameters into a tuple.
- def sum(*args):
- pass
Similarly, **kwargs is used for handling an arbitrary number of keyword parameters, which are collected into a dictionary.
- def sum(**kwargs):
- pass
To enforce named parameter passing, use the asterisk * symbol. After this symbol, all subsequent parameters must be explicitly named.
- def sum(a, *, b, c):
- pass
From Python 3.8 onwards, the `/` symbol allows you to define parameters that must be passed positionally.
- def sum(a, b, /, c, d):
- pass
This specifies that parameters a and b are strictly positional.
Object Passing: By Reference
It's crucial to understand that in Python, objects are passed by reference. This means that the function receives a reference to the actual object in memory, not a separate copy.
As a result, the function can alter the original object.
Consider this practical example:
- def foo(x):
- x.append(4)
- return x
- myList = [1, 2, 3]
- y = foo(myList)
- print(y)
- print(myList)
In this scenario, the reference of a list is passed to the function foo(), which then modifies the list by adding an element.
This modification reflects in the original list.
[1, 2, 3, 4]
[1, 2, 3, 4]
To prevent unintended modifications to the original object, it's advisable to pass a deep copy of the object to the function. This ensures that any changes made within the function are isolated from the original object.
The return Statement
The return statement is crucial in Python, as it dictates what value a function will pass back to its caller. Let's delve into how it works.
Consider the following example:
- def square(x):
- x = x**2
- return x
- y = square(3)
- print(y)
Here, the function 'square' receives a number, calculates its square, and returns this value. In our example, it computes the square of 3, resulting in 9.
9
It's important to note that functions in Python always return a value, whether explicitly defined or not.
By using the return statement, you explicitly specify the value to be returned. If, however, the return statement is omitted or never reached, Python defaults to returning a None object implicitly.
For instance, if you remove the 'return x' line from our function, it still processes the square of 3 but ends up returning None, as no explicit return value is provided.
- def square(x):
- x = x**2
- y = square(3)
- print(y)
None
Another key point is that a function can only return a single value via the return statement. But what if you need multiple results? Python offers a neat trick for this. You can encapsulate multiple values into a single entity like a list or a tuple.
Take this enhanced version of our function, which now calculates and returns both the square and the cube of the input:
- def square(x):
- y1 = x**2
- y2 = x**3
- return (y1, y2)
- y = square(3)
- print(y)
This time, the function neatly packages the square (9) and the cube (27) of the number into a tuple, returning both values simultaneously.
(9, 27)
To access these results, simply extract them from the tuple:
print("The square of x is " + str(y[0]))
print("The cube of x is " + str(y[1]))
And there you have it, the function efficiently returns multiple results:
The square of x is 9
The cube of x is 27
This technique opens up possibilities for functions to be more versatile and return-rich in Python.
Function Labels
It's crucial to understand that functions are Function type objects and their names are essentially references to these function objects.
Bearing this in mind, if you repurpose a function's label for something else in your code, such as assigning a value to a variable, you'll lose the ability to call the original function.
Consider the following script as an illustration:
- # defining the function
- def sum(a,b):
- result = a + b
- return result
- # first function call
- ans = sum(2,3)
- print(ans)
- # reassigning the label
- sum = 5
- # attempting a second call
- ans = sum(4,5)
- print(ans)
This example shows how the "sum" label, initially assigned to a function, is later used for a variable. As a result, the first call to the function works as expected, but the second call fails, indicating that the function reference has been overwritten.
5
Traceback (most recent call last):
File "/home/main.py", line 14, in <module>
ans = sum(4,5)
TypeError: 'int' object is not callable
Hence, it's important to be mindful about function naming and avoid reusing names within the same scope of your program.
The Power of Docstrings
Placing a string literal as the very first statement in a function's code block turns it into a docstring, accessible through the function's __doc__ attribute or by using the help() function.
This practice of using docstrings is invaluable for providing inline documentation and guidance on a function's purpose and usage.
For instance, take a look at this function:
- # defining the function
- def sum(a,b):
- """Calculates the sum of two numbers"""
- result = a + b
- return result
- print(sum.__doc__)
Here, the first instruction inside the function is a descriptive string.
When you print the attribute sum.__doc__, Python conveniently displays the docstring.
Calculates the sum of two numbers
Alternatively, accessing the docstring is also possible through the help() function:
help(sum)
In both instances, you're presented with the same helpful description embedded in the function.
Help on function sum in module __main__:
sum(a, b)
Calculates the sum of two numbers
Docstrings are a practical way to embed documentation within your Python code, elucidating the function, class, or module's purpose and mechanics.