  # Create and Use Functions in Python

Published on  Name
Sahil Fruitwala
@Sahil_Fruitwala  What is a function? What does a function do? As the name suggests function does a specific task. This task can be used repeatedly or once as per the use case. The main purpose of a function is to separate the logic into different blocks. We can create our functions or use any of the available in-built functions in python.

Syntax:

``````def function_name(parameters):
"""docstring"""
statement(s)
return expression
``````

We can see in the syntax that to create a function we need to use the `def` keyword following the function name. Parameter(s)/ Argument(s) is the only way through which we can pass data to the function. We can add a docstring to explain the use of function and its parameter(s). A function can return a value if desired. It is not compulsory to return something.

Once we define the function, to use it we need to call that function. Let's assume I have created a function named `odd_or_even`. To call this function, I can write like `odd_or_even()`. And if this function is expecting some argument(s), I can write it like `odd_or_even(2)`.

# Sum of Two Numbers

If we want to just print the sum of two numbers or just to see the sum of two numbers, we do not need to return anything. And if we try to assign it to a variable we get `None` as the value.

``````def sum_num(num1, num2):
total = num1 + num2
print(total)

sum_num(5,10)

# OUTPUT: 15
``````
``````def sum_num(num1, num2):
total = num1 + num2
print(total)

temp = sum_num(5,10)
print(temp)

""" OUTPUT:
15
None
"""
``````

Now, if we want to return the sum then we can do using the following code.

1.py
``````def sum_num(num1, num2):
total = num1 + num2

temp = sum_num(5,10)
print(temp)

# OUTPUT: 15
``````

# Keyword arguments

In general, we need to pass arguments in a specific order to a function. But, using keyword arguments we can pass arguments in any order. Let's understand it by an example of division. In the example below, if we want `3/2` then we will write `divide(3,2)`.

``````def divide(num1, num2):
return num1/num2

ans = divide(3,2)
print(ans)

# OUTPUT: 1.5
``````

But now, by mistake, we wrote `divide(2,3)`. This error can make the whole logic wrong.

``````def divide(num1, num2):
return num1/num2

ans = divide(2,3)
print(ans)

# OUTPUT: 0.6666666666666666
``````

To save yourself from this kind of mistake we can use keyword arguments. This is just a normal argument passing, but instead of passing only value, we will pass the variable name as well.

``````def divide(num1, num2):
return num1/num2

ans = divide(num1=3, num2=2)
print(ans)

# OUTPUT: 1.5
``````

So, now we can pass data in any order and this way logic will be intact.

``````def divide(num1, num2):
return num1/num2

ans = divide(num2=2, num1=3)
print(ans)

# OUTPUT: 1.5
``````

This is one of the best practices for function in python.

# Variable Length Arguments

In some cases, we don't know the number of arguments we will receive in function. Or we do not want to restrict the function with a specific number of arguments. In this kind of situation, we can use variable-length arguments. There are two types of variable-length arguments:

1. *args (Non-Keyword Arguments)
2. **kwargs (Keyword Arguments)

## 1. *args (Non-Keyword Arguments)

In non-keyword arguments, we just pass n number of data to the function. `*args` is not the fixed name of non-keyword arguments. We can use any name. It is just a standard to use *args.

Let's assume, we are asking users to enter the fruits they have. Noe, every user might have a different number of fruits. To save or to operate on all fruits entered by users, we can use non-keyword arguments.

``````def fruit_list_operation(*fruits):
for fruit in fruits:
print(fruit, end=",")

fruit_list_operation("apple", "banana")

print()

fruit_list_operation("apple", "banana", "grape", "mango")

""" OUTPUT:
apple,banana,
apple,banana,grape,mango,
"""
``````

Here, we have used for loop as `*args` will create a sequence data. As you see, when we pass 2 fruits loop runs for 2 times and 4 times in the second case.

The `print(fruit, end=",")` function is used to notify the interpreter that does not end the statement with a new line. Instead, use comma(,) to end the statement. And when we used the `print()` function, it just wrote a new line and moved on.

## 2. **kwargs (Keyword Arguments)

The variable-length keyword argument is almost the same as the variable-length non-keyword arguments. The only difference we use this variable-length keyword argument function when we do not know how many keyword arguments we will be getting.

``````def my_project(**kwargs):
for key, value in kwargs.items():
print("%s == %s" % (key, value))

my_project(frontend = "Angular", backend = "Python", database="MongoDB")

""" OUTPUT:
frontend == Angular
backend == Python
database == mongodb
"""
``````

# Default Parameter Value

When we want to use some default value if the argument is not passed to a function, we can use the default parameter. We can use any number and any datatype as the default parameter. There is just one condition we have to use the default value argument as the last parameter of the function.

``````def division(num1, num2=2):
print(num1/num2)

division(16,4)
division(16)

""" OUTPUT:
4.0
8.0
"""
``````

Let's see what happens if we keep the first argument as the default argument.

``````def division(num1=2, num2):
print(num1*num2)

division(16,4)
division(16)

""" OUTPUT:
File "functions.py", line 1
def division(num1=2, num2):
^^^^
SyntaxError: non-default argument follows default argument
"""
``````

# Docstring

As we have seen in the syntax, the first commented statement in any function is considered as the docstring. Docstring is nothing but some commented statements explaining the use of the function, its arguments and the return expression. To print or to get the docstring we can use the following syntax: `*function_name*.__doc__`. Let's see an example to understand the concept of the docstring.

``````def is_odd(num1):
"""Function to check if the number is odd or not.

Parameters:
num1 (float): number to be checked

Returns:
is_odd (boolean): true if number is odd

"""
is_odd = num1 % 2 != 0
print(is_odd)
return is_odd

is_odd(16)
is_odd(1)
print("-"*15)
print(is_odd.__doc__)

""" OUTPUT:
False
True
---------------
Function to check if the number is odd or not.

Parameters:
num1 (float): number to be checked

Returns:
is_odd (boolean): true if number is odd
"""
``````

When we use a third-party library or even some python in-built library we can use docstring to understand the use of a specific function.

``````print(range.__doc__)

""" OUTPUT:
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When a step is given, it specifies the increment (or decrement).
"""
``````

# Conclusion

That was it. Thank you for reading.

Let me know if you need any help or want to discuss something. Reach out to me on Twitter or LinkedIn. Make sure to share any thoughts, questions, or concerns. I would love to see them.

Till the next time 👋