A Python function is a block of code that performs a specific task when it is invoked.
Functions are especially useful when a fragment of code performing the same task appears multiple times in a program. Isolating that code in a single function reduces redundancy, improves readability, and makes the code easier to modify. Functions are also useful for organising a program into named, logical steps, even when each one is only called once.
Defining a Function
A function is created using the def keyword, followed by the function name and a set of parentheses as follows:
def function_name():
# Function body
pass
A function is called by writing its name followed by a set of parentheses. This is commonly referred to as function invocation.
function_name()
Let's view an example of creating and invoking a function. The function uses an optional parameter rate, a concept I will revisit later in this article.
# creating a function that adds VAT to a price
def add_vat(price, rate=0.16):
vat = price * rate
total = price + vat
return total
# invoking the function in a print statement
print(f"Item 1 : Ksh {add_vat(1000)}")
print(f"Item 2 : Ksh {add_vat(2500)}")
This function outputs:
Item 1 : Ksh 1160.0
Item 2 : Ksh 2900.0
How Do Functions Work?
Python typically runs the code file from top to bottom. However, when a function is invoked, Python jumps to the function, the body of the function is executed, and Python returns to the point directly after the point of invocation.
Note: One must not invoke a function before it has been defined or otherwise made available in the current scope, as this causes the error NameError: name 'function_name' is not defined.
Function Parameters and Arguments
Parameters
A parameter is a variable defined in a function definition that acts as a placeholder for a value that will be passed to the function or supplied through a default value.
def function_name(parameter):
# Function body
pass
Python supports required parameters and optional parameters.
Required parameters are parameters that must receive a value when the function is called. If a required parameter is not provided with a value, Python raises a TypeError.
Optional parameters are parameters that have default values assigned in the function definition. If an argument is not provided for an optional parameter, Python uses its default value.
Note: In a function definition, parameters with default values must come after parameters without default values. Violating this rule raises a SyntaxError ("non-default argument follows default argument").
Arguments
An argument is a value that is passed to a function during invocation. The argument supplies a value to a corresponding parameter so that the value can be used in the function body.
function_name(argument)
Let's view how the concepts of parameters and arguments work with an example.
Let's create a greet function where name is a required parameter, while greeting is an optional parameter because it has a default value of "Hello".
When we invoke the function, we can pass an argument for both parameters or only pass an argument for the name parameter, in which case the default value for the greeting parameter is used.
def greet(name, greeting="Hello"):
print(greeting, name)
greet("John")
greet("Doe", "Hi")
Output:
Hello John
Hi Doe
Note: When using positional arguments, the number of arguments must be at least the number of required parameters and no more than the total number of parameters (unless the function uses *args). Optional parameters do not need to receive arguments because Python uses their default values.
Python also supports *args, which allows a function to accept a variable number of positional arguments, and **kwargs, which allows a function to accept a variable number of keyword arguments.
def show_all(*args, **kwargs):
print(args)
print(kwargs)
show_all(1, 2, 3, name="John", city="Nairobi")
Output:
(1, 2, 3)
{'name': 'John', 'city': 'Nairobi'}
Here, args collects the positional arguments into a tuple, while kwargs collects the keyword arguments into a dictionary.
Argument Passing
There are two common methods of passing arguments to parameters.
Positional Argument Passing
In this technique, the argument in the nth position is assigned to the parameter in the nth position.
Example:
def show_person(name, age):
print(name, age)
show_person("John", 25)
Output:
John 25
Keyword Argument Passing
This method allows passing arguments by specifying the parameter names to which they will be assigned.
Example:
def show_person(name, age):
print(name, age)
show_person(age=25, name="John")
Output:
John 25
Note: You can combine positional and keyword arguments in the same function invocation. However, positional arguments must be placed before keyword arguments.
Example:
def describe_person(name, age, city):
print(name, age, city)
describe_person("John", age=25, city="Nairobi")
Output:
John 25 Nairobi
Return
When a function is called and its body is executed, the function implicitly returns None if no return value is specified, and code execution returns to the point after which the function was called.
However, one will often need to get a value from a function to use in other parts of the code. This is done using the return statement.
The return statement allows a function to send a value back to the code that called it. This value can be assigned to a variable and used in other parts of the code.
When the return statement is encountered, it immediately terminates the function's execution. The function evaluates the return expression and sends the resulting value back to the caller.
Example:
def add(a, b):
return a + b
result = add(10, 5)
print(result)
Output:
15
Global and Local Scope
Global Scope
A variable defined outside of any function is a global variable. It can generally be accessed inside functions, subject to Python's scope rules.
Example:
message = "Hello"
def greet():
print(message)
greet()
Output:
Hello
Local Scope
A variable defined inside a function is generally a local variable. It can only be accessed within the function where it is defined. Attempting to access it outside the function causes a NameError if the variable is not defined elsewhere.
Example:
def greet():
message = "Hello"
print(message)
greet()
print(message) # raises a NameError
Output:
Hello
NameError: name 'message' is not defined
In this example, message is a local variable and cannot be accessed outside the greet() function.
The global Keyword
Reading a global variable inside a function needs no special keyword, but assigning to one does. The global keyword allows a function to refer to and modify a variable defined in the global scope.
Example:
count = 0
def increment():
global count
count += 1
increment()
print(count)
Output:
1
In this example, global count tells Python that the function should use the global variable count rather than create a local variable with the same name. Without it, count += 1 would raise an UnboundLocalError, because Python would treat count as a local variable that is used before it has been assigned a value.
Recursion
Recursion is a technique in which a function invokes itself. When using recursion, one must define a termination condition, also known as a base case, to stop the function from calling itself indefinitely. Without a proper termination condition, the program may continue calling the function until Python raises a RecursionError.
Example:
def countdown(n):
if n <= 0:
print("Done!")
else:
print(n)
countdown(n - 1)
countdown(3)
Output:
3
2
1
Done!
In this example, the base case is n <= 0. Once the condition is met, the function prints "Done!" and stops making recursive calls.
Conclusion
Functions are one of Python's most important building blocks. They let you package a task once and reuse it, which reduces repetition and makes code easier to read and maintain. Parameters and arguments, passed by position or by keyword, make functions flexible, and return lets them hand results back to the caller. Understanding scope, including when global is needed, helps you avoid subtle bugs. Recursion shows how a function can solve a problem by calling itself, as long as it has a clear base case. With these fundamentals, you can write modular, reusable, and well-organised programs.
Top comments (0)