Functions in Python

What is a Function in Python?

A Function in Python is utilized to use the code in more than once in a program. It is likewise called methods or procedure. Python gives you numerous inbuilt capacities like print(), however it likewise offers opportunity to make your own functions.

Declaring a Function

Frequently enough, built-in functions can’t get the job done even beginners. In such a case, there is no choice yet to make your own function utilizing the keyword def (derived from define). Let’s have a look at the syntax:

def function_name(parameter1, parameter2, ...):
    # function's body
    ...
    return "return value"

After def, we write the name of our function (to invoke it later) and the names of parameters, which our function can acknowledge, enclosed in parenthesis. Do not miss the colon at the end point. The names of a function and its parameters follow a similar convention as variable names, that is, they ought to be written in lowercase with underscores between words.

An indent of 4 spaces shows the interpreter where the function’s body begins and where it ends. All statements in the function’s body must be indented. You can make computations inside your function and utilize the return keyword to send the outcome back. Just when the space is missing, the meaning of the function ends.

Afterward, the parameters take on values passed in a function call. Those values we pass to a function are known as arguments The main differentiation among parameters and arguments is that we introduce parameters in a function definition and give arguments (some particular values) in a function call.

# Function definition
def add(x, y):
    return x + y
 
 
# Function calls
a = add(30, 5) 
b = add(a, 10)

In case you don’t want to pass any arguments, the round brackets remain empty:

def welcome():
    print("Hey!!!")

You can also declare an empty function with pass statement:

def passing(param):
    pass

When you choose to call passing() with an arbitrary value as its argument, nothing will happen. So pass is just a placeholder, but your code will be valid with it.

Parameter vs. Arguments

In fact, parameters are just aliases for values, which can be passed to a function.

Consider the following example:

def postcard(address, message):
    print("Sending the postcard to", address)
    print("With the message:", message)
 
 
postcard("Hillary, 97", "Hello, bro!")
 
postcard("Piccadilly, London", "Hi, London!")

Output

This function takes exactly 2 arguments, so you will not be able to execute it with more or less than 2 arguments:

def postcard(address, message):
    print("Sending the postcard to", address)
    print("With the message:", message)
 
 
postcard("Hillary, 97")

Output

Execution and Return

Our previous function just performed certain activities, however it didn’t have any return value. Nonetheless, you should figure something in a function and return the outcome sooner or later. Check the accompanying example:

def temp(temp_c):
    temp_f = temp_c * 9 / 5 + 32
    return round(temp_f, 2)
 
water_bp = temp(100)
print(water_bp)

Output

The keyword return is utilized to demonstrate what values the function outputs. Fundamentally, it is the consequence of the function call. In this way, in the example above, we’ve put away the value returned by our function in the variable water_bp. Just to be sure, we printed the result.

One more comment is that functions don’t really have return values back. The notable print() function doesn’t, in fact, return anything. Understand from the below code:

new_char = print("Hey, you remember me?")
print(new_char)

Output

We declared the variable new_char and invoked print(). Obviously, the function was executed. But the variable itself turned out to be the None object, which means the called function had nothing to return. The value of new_char is None.

Python interpreter stops performing the function after return. But what if the function body contains more than one return statement? Then the execution will end after the first one. Please, keep that in mind!

Kwargs

With *args you can create more adaptable functions that accept a varying number of positional arguments. Luckily, in Python, you can work with keyword arguments along these lines.

Multiple Keyword Argument

We should know that the ** operator is used to pass a varying number of keyword arguments into a function. **kwargs gathers all possible additional values in a dictionary with keywords as keys.

By convention, individuals utilize unique names for this sort of arguments: *args for positional arguments and **kwargs for keyword arguments, however you can consider them anything you desire. The primary concern is that a single asterik * for positional arguments and **kwargs associates a value with a name, or keyword. Thus, **kwargs contrasts from *args in that you should allot keywords.

def capital(**kwargs):
    for key, value in kwargs.items():
        print(value, "is the capital city of", key)
 
 
capital(Canada="Ottawa", Estonia="Tallinn", Venezuela="Caracas", Finland="Helsinki")

Output

Note that the names in a call are without quotes. That is not a mistake. Moreover, the names should be valid, for example, you cannot start a keyword with a number. Follow the same naming rules as for variables.

It is also possible to combine *args and **kwargs in one function definition:

def func(positional_args, defaults, *args, **kwargs):
    pass

The order is crucial here. Just as non-keyword arguments precede keyword arguments, *args must come before **kwargs in this case. Otherwise, both when creating and calling a function with *args and *kwargs in the wrong order, a SyntaxError will appear:

Unpacking in function calls

There are two unpacking operators in Python: a single asterisk * unpacks elements of an iterable object and a double asterisk ** works with dictionaries. Let’s try to get key-value pairs from a dictionary and pass them as keyword arguments using a double asterisk **:

def say_bye(**names):
    for name in names:
        print("Au revoir,", name)
        print("See you on", names[name]["next appointment"])
        print()
 
 
humans = {"Laura": {"next appointment": "Tuesday"},
          "Robin": {"next appointment": "Friday"}}
 
say_bye(**humans)

Output

Partial Functions

Partial functions are those functions which allow us to fix a certain number of arguments of a function and generate a new function.

from functools import *

def add(a, b, c): 
    return 2 + a + 10 / b * c 

syn = partial(add, c = 25, b = 4) 

print(syn(3)) 

Output

Partial functions can be used to derive specialized functions from general functions and therefore help us to reuse our code.