Functions in Python
By Varun Dwarki
Python is the preferred choice of programming language for developers, data scientists, engineers, and programming enthusiasts everywhere. You can use it for simple scripting to build sophisticated web applications. This article will help you get acquainted with the nuances of Functions in Python and how to effectively take advantage of them.
The topics that you will learn in this article are:
- What are Functions in Python
- Why Use Functions?
- Coding Functions
- Defining Functions
- Specifying Function Docstring
- Python Namespace and Scope
- Local Variables
- The global Statement
- Argument Passing in Python
- Types of Python Arguments
- Return Values
- Conclusion
What are Functions?
Functions are a simple way to decompose a complex large problem into intellectually manageable chunks. In technical terms, a function is a set of statements or instructions that perform a certain task, grouped together as a unit, so they can be run more than once in a program.
If you ignore the code for now (which will be covered later), you can see that a function is simply a block of instructions, packaged as a unit, just like a box. This sort of practice allows us to write code that is both reusable and easier.
Before we get into the technical details, let us establish a clear picture of why functions are important.
Best-suited Python for data science courses for you
Learn Python for data science with these high-rated online courses
Why Use Functions in Python?
Functions are a universal programming structure and a very important content in any programming language. Listed below are a few reasons why we need them,
Reduce Code Duplication: Functions are the simplest way to package your code to use it at multiple places at multiple times
Procedural Decomposition: Functions are a tool for splitting a complex system into well-defined, meaningful, intellectual pieces. For instance, you can divide your “make a pizza” task into smaller chunks such as mixing the dough, rolling it out, baking it, and so on
Hide Implementation Details: Just by looking at the function name, you can pretty much understand the purpose of the function. You are not forced to delve into implementation details
Now that you are aware of what functions are and why they are important, let us explore the tools used to code functions in Python.
Coding Functions
You might have probably come across or used some functions in your course of programming journey. For instance, you might have to use a built-in int function to create an integer object, or len built-in function to find the number of items in a sequence object, and so many others. These are nothing but the built-in functions that Python offers to a user. Each of these functions performs a single, well-defined task.
To use these functions, all you have to know is its name, purpose, the arguments it takes, and the values it returns. That is unless you want to create a new function on your own. We call them custom functions. In this article, we will explore how to define and call custom functions. These functions behave the same way as the normal built-in functions except for a few additional details that you might have to keep in mind when working with them.
Defining Functions
Functions in Python are defined using the keyword def, followed by the name of the function, terminated by a pair of braces (which may or may not have input parameters, and at last, a colon ( : ). Here’s a simple example of a function square, that calculates the square of its argument, when called.
#Example 1
def square(num):
“””Calculate the square of number.”””
return num ** 2
square(2.5)
You should know that, unlike functions in compiled languages such as C, in Python def is an executable code. By that I mean, that function that you define does not exist until Python reaches and runs the def. When Python runs a def statement, it creates an object and assigns a name to it.
In the above example, the function name is “square”. The def statement just defines the function but does not call. Once the function is defined, you can call (run) the function in your program by using the function name, followed by parenthesis (parameters if any). From the above example, we have
square(2.5)# Arguments in parentheses
Function objects may also have an arbitrary list of parameters representing the data on which the function has to perform its task. The square function has a single parameter named num, the data value that has to be squared. Post the colon ( : ), the indented lines are the function’s block, the set of instructions that perform the function’s task.
Once the function finishes the execution, the control is returned to its caller, i.e. the line of code that has called the function. In the example above, the return statement first squares the number num, then terminates the function, and returns back the control to the caller.
Specifying Function Docstring
Let us consider an example: Calculating the factorial of a given number.
#Example 2
def factorial(n):
“””Returns factorial of a number.”””
m = 1
return m if n < 2 else n * factorial(n-1)
print(factorial(5))
print(type(factorial))
print(help(factorial))
factorial.__doc__
The functions that are used in real-life applications are often complex, in the sense, it might take time to go through the entire code to figure out its purpose. Wouldn’t it be nice if there is a brief description that explains the function’s purpose? That’s exactly why it is suggested to have the first line in a function’s block as docstring that explains the purpose. In the above example, we have:
“””Returns factorial of a number.”””
One of the function attributes __doc__ , is used to generate the help text of a Python object. You can print a function’s docstring (nicely formatted one) using help()function. If you are just interested in the raw docstring without any formatting, you can use the __doc__ function.
Another interesting thing in the above example is the variable m inside the factorial function. It is called a local variable and is visible only to lines of code inside the function defined. So, what do I mean by that?
Check out top python interview questions
Python Scopes
Now that you are ready to build your own functions, you should know how Python deals with the names that you use in your code. Let’s say you are looking for a book, so you go to the library and ask the librarian about the location of the book. The librarian tells you something like, “Third floor, section C, row 5”. So, there you go in search of your book much more easily.
Similarly, Python tries to keep your code organised by using the concept of namespace – a place where names live. Since names are not declared ahead of time, Python uses the location in your code where you have defined the name, to determine the scope of the name’s visibility in the code. To make this easier to understand, let us consider a simple example.
#Example 3
import math #global scope
X = math.pi
def area(r):
Z = X * r * r # r and Z: local scope
return Z
area(2)
In the above example, the scope of variable X is global, which is to say that X is assigned at the top level of the enclosing module file and is just referenced by the function area. Likewise, the variables r and Z are local variables.
They are local to the function area (in our example) and they serve as temporary names that you need only while a function is running. By default, all the names that are assigned within a function definition belong to the local scope. Now, what if you want to change the value of the variable X inside the function? How can you achieve that?
The global Statement
You can use global statements to change one or more global names (the names that live outside a def statement at the top level) inside your function.
#Example 4
var = 99 #global variable
def local1():
var = 88
print(var) #local variable with the same name as global variable
def global1():
global var
var = 77
print(var) #using global statement
print(var)
local1(); global1()
In the above example, we were successfully able to change the value of global variable X inside the function global1 using the keyword global. You will also notice that names that are assigned inside a def do not clash with variables assigned outside the def, even when you use the same names.
Note: It’s suggested to minimise the use of global variables unless you cannot avoid using them. Variables inside def are local for a reason and changing global variables can make your code complex, difficult to understand and debug.
Check out Python Based online Courses
Passing Arguments
Now let us explore the powerful syntax that Python offers to declare function parameters and how to pass arguments into them. Before we jump in here are some simple points regarding argument passing that you should remember:
- Passing arguments to a function is nothing but assigning objects to local variable names
- Within the scope of the function, assignment to argument names does not affect the caller
#Example 5
def func(A):
A = 10 # we are defining local A, not changing the global one
A = 3
func(A)
print(A)
- Modifying the passed-in mutable objects in place may affect the caller
#Example 6
def func(X, Y):
X = 10 # we are defining local A, not changing the global one
Y[1] = ‘Jim’ # Y is mutable object. This affects the caller
X = 3
Y = [1, 2, 3]
func(X, Y)
print(“The value of X after the function call:”, X)
print(“The value of Y after the function call:”, Y)
Types of Arguments
There are xxx ways of specifying arguments. Let us explore each of these in brief.
Positional Arguments
Positional arguments are the basic type of arguments where the passed argument values are matched to argument names in the function header from left to right.
#Example 7
def area_rectangle(l, b, w):
area1 = l * b * w
return area1
print(area_rectangle(5, 4, 8))
Keyword Arguments and Default Values
Functions in Python can also be called using keyword arguments, where the caller can specify which argument name in the function header is to receive the value by using the argument name in the function call. Let us now modify the above example using the keyword arguments.
#Example 8
def area_rectangle(length, breadth, width):
area1 = length * breadth * width
return area1
print(area_rectangle(width = 8, length = 5, breadth = 4))
Note that each keyword argument in a call has the form name=value. Since keyword arguments are matched by name, their order doesn’t matter. In the above example, the function call passes the arguments in the order width, length, and breadth. Whereas in the function header the parameters are in the order length, breadth, and width. Please note that this might have limitations when you are passing arguments of different types.
Explore Free Online Courses with Certificates
Default Argument Values
Python allows you to specify a default value for one or more arguments to receive if the function call passes too few values. Even here, it uses the name=value syntax.
#Example 9
def area_rectangle1(length, breadth = 7, width = 2):
area1 = length * breadth * width
return area1
#keyword arguments
print(area_rectangle1(width = 8, length = 5, breadth = 4))
#default argument values: length=5, breadth=7, width=2
print(area_rectangle1(length = 5))
#keyword arguments after positional arguments
print(area_rectangle1(1))
print(area_rectangle1(11, 12, 13))
print(area_rectangle1(10, breadth = 10))
From the above examples the important points that you can infer are as follows:
- Default argument allows you to create a function that can be called with fewer arguments
- They are calculated when the function is defined, not when it is run
- You cannot specify a default argument on the left of the positional argument
- In a function call, you should always place keyword arguments after positional arguments. Doing so will give you an error saying “SyntaxError: positional argument follows keyword argument”
#Example 10
def area_rectangle12(length, breadth = 7, width = 2):
area1 = length * breadth * width
return area1
print(area_rectangle(length = 4, 42))
Variable Arguments
Python allows you to define a function that can receive any number of arguments by using one or more *characters. Do not confuse it with the pointers like in C language. Python doesn’t have the concept of pointers!
Let’s try to understand with the help of an example: Gathering variable positional arguments with *
#Example 11
def stud_details(*args):
print(“Student Details (Variable Positional Arguments):”, args)
def stud_details1(id, name, *args):
print(“Required Positional Arguments:”, id, name)
print(“Rest of the Positional Arguments:”, args)
stud_details(“1JS13CS028”, “Jim”, 25, “Computer Science”, ‘and….’)
stud_details1(“1JS13CS027”, “Sam”, 25, “Computer Science”, ‘other details…’)
The * operator groups multiple positional arguments into a tuple of parameter values, according to how the function is called. Similarly, you can do the same for keyword arguments using two asterisks (**).
#Example 12
def print_kwargs(**kwargs):
print(kwargs)
print_kwargs(id=1, age=22)
print_kwargs(**{‘id’: 1, ‘age’: 22})
print_kwargs(**dict(id=1, age=42))
You can use two asterisks (**) to group a variable number of keyword arguments into a dictionary, where the argument names in the function call are keys, and the values of those arguments are corresponding dictionary values. Apart from these, I suggest you explore positional-only arguments, keyword-only arguments, and both of them combined.
Just one more thing about passing arguments to functions. So, in Python do we pass arguments using pass-by-value or pass-by-reference? In Python, the arguments are always passed by reference or often referred to as pass-by-object, because pretty much everything in Python is an object.
Explore Popular Online Courses
Function Returning Values
We have briefly discussed how the function returns values in the earlier section. In Python, a function uses a return function to send back a result object to the caller. A function always returns something, even when function return() is not explicitly called.
In this case, it just returns None object, the default result. There is another advanced way of returning results, which is using the yield function and you should definitely check that out.
That’s it, folks! With this, we have reached the end of the article. Functions are a very basic and important topic of every programming language, including Python. Master them and you will know how to code smartly by reusing the code.
________________
If you have recently completed a professional course/certification, click here to submit a review.
This is a collection of insightful articles from domain experts in the fields of Cloud Computing, DevOps, AWS, Data Science, Machine Learning, AI, and Natural Language Processing. The range of topics caters to upski... Read Full Bio