Functions are one of the core concepts in many programming languages. With using functions, you write code once, then using many times without rewriting. Because of that, you save time and effort.
To be able to write maintainable and readable code, you should have composed useful functions.
Therefore, you should take extra care about functions. In Python writing functions is easy. At the end of the post, you learn how to write functions smoothly and efficiently.
Besides that, why the prominent software engineers like Kent Beck, Martin Fowler, and Robert C. Marting gives particular importance to the subject.
What Are Python Functions?
Functions are code blocks which do a specific task. They take input, runs, and returns an output. Python functions save you of writing the same code again and again and lead to code reusability and avoid redundancy.
You Define Python Functions Using Def Keyword
Syntax:
def functionname(parameter1, parameter2, ...):
body
Passing Arguments
You can pass arguments to functions in a variety of ways.
For example:
def print_fullname(firstname, lastname):
print(firstname, lastname)
print_fullname('john', 'doe')
outputs:
john doe
Python assigns the argument ‘john’ to firstname parameter, vice versa ‘doe’ to the second parameter, lastname.
On the other hand, calling the function in reverse order like:
print_fullname('doe', 'john')
outputs:
doe john
In the preceding example, firstname takes the ‘doe’ and lastname takes the ‘john’ value.
Keyword Arguments
Python is a flexible language. Using keyword arguments, you don’t have to send parameters in the defined order.
Calling the preceding function (print_fullname) with keyword arguments:
print_fullname(firstname='john', lastname='doe') # prints John Doe
print_fullname(lastname='doe', firstname='john') # output is the same, prints john doe
You enter parameters in ‘parametername=value’ format, and the order would be not significant.
Passing Arbitrary Number Of Arguments Using Asterisk Symbol
Python allows a function to take an arbitrary number of arguments. If you enter an asterisk symbol before the parameter definition, it collects as many arguments as the calling statement provides.
def show_fruits(*fruits):
for fruit in fruits:
print(fruit)
show_fruits('apple', 'grape', 'banana', 'cherry')
outputs:
apple
grape
banana
cherry
Passing Arbitrary Number Of Arguments As Key-Value Pairs (Double asterisk)
You can send key-value pairs in arbitrary numbers to python functions.
def print_car_attr(**car):
for key, value in car.items():
print(key + '', value)
print_car_attr(model_year=2015, color='red', fuel='diesel')
outputs:
model_year: 2015
color: red
fuel: diesel
Python creates an empty dictionary (car) and inserts the key-value pairs provided by the calling statement into the car dictionary.
Return Value
Generally, you use functions to do some job and return some value. In this case, you enter a return statement:
def multiply(a, b):
return a * b
c = multiply(5, 40) # return value is set to c variable
print(c) # prints 20
It is not mandatory to return a value from a python function. However, even if you don’t return a value, a python function returns implicitly a value, called None.
def no_return_func():
pass # pass is a statement, which does not do anything.
# just to please Python interpreter
c = no_return_func()
print(c)
outputs:
None
Lambda Or Anonymous Functions
Functions in Python are first-class functions. What does that mean? You can assign functions to variables. Also, send functions as an argument to another function.
Some built-in functions like map, filter, and reduce function, take functions as a parameter.
In these possible scenarios, defining functions using the standard def keyword every time would be tedious.
Because of that, Python permits you defining lambda (anonymous) functions:
lambda arguments: expression
The left side of the colon shows the arguments; the right side function body.
total_list = [1, 2, 4, 5, 4, 6, 8, 10, 11, 12]
odd_number_list = list(filter(lambda x: (x%2 != 0) , total_list))
print(odd_number_list)
outputs:
[1, 5, 11]
Best Practices On Functions
What are the best practices on Creating Functions?
Gems from Robert C. Martin (aka Uncle Bob):
- Function names should make the intention explicit. Meaningful names are essential.
- Functions should be as small as possible.
- Should do one thing and do it well.
- Related with the third item, don’t use boolean parameters.
Martin Fowler gives another good strategy:
I look at a method that is too long or look at the code that needs a comment to understand its purpose. I then turn that fragment of code into its own method.
Refactoring, Martin Fowler
Naming Convention Of Functions
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
Parameter names follow the same convention as function names.
https://www.python.org/dev/peps/pep-0008/
FAQ
Can you define a function within a function in Python?
Nested functions or inner functions is possible in Python.
def uppercase_fullname(firstname, lastname):
def upper_case(name):
return name.upper()
return upper_case(firstname) + ' ' + upper_case(lastname)
print(uppercase_fullname('john', 'doe')) # JOHN DOE
However, you cannot call the inner function directly from the outer.
Can a function call itself in Python?
Yes. It is called a recursive function. The classic example of recursion is finding Fibonacci numbers. The number is equal to the sum of the preceding two number:
def fibonacci(n):
if n==1:
return 0
# Second Fibonacci number is 1
elif n==2:
return 1
elif n>2:
return fibonacci(n-1) + fibonacci(n-2)
for indx in range(10):
print(fibonacci(indx))
outputs:
0
1
1
2
3
5
8
13
21
34
Conclusion
Small and manageable functions make your code readable and testable. In Python creating and using function is simple and efficient. You can send arguments in a couple of ways; Positional arguments, keyword arguments or to be able to send an arbitrary number of parameters gives you flexibility as you design your functions.
See another concept related to code reusability: Python Modules.