Create and Use Functions in Python
Tags: beginners, programming, tutorial, python
Published: 2022-09-17 13:33:58

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:

```python
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.

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

sum_num(5,10)

# OUTPUT: 15
```

```python
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.

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

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)`.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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](https://twitter.com/sahil_fruitwala) or [LinkedIn](https://www.linkedin.com/in/sahilfruitwala). Make sure to share any thoughts, questions, or concerns. I would love to see them.

Till the next time 👋

---

If you like this blog you can subscribe to my [Newsletter](https://newsletter.sahilfruitwala.com/) for more amazing content.