Functions in Python

In programming, abstraction refers to the idea of not necessarily knowing (exactly) how something works but knowing how to properly use it instead. For example, you may not know what a module of code consists of or how it was built, but you can still use it to achieve your intended results if you know how to use it and what to use it for.

Decomposition refers to the idea of breaking a problem down into smaller, self-contained pieces. For example, you may divide a very large code project into smaller, individual pieces of code that you can later combine to achieve a finished project.

Both abstraction and decomposition are important ideas that help simplify things when working with code that can easily get complicated and messy (such as in large projects).

Functions

Functions are reusable pieces/chunks of code and are one way to implement the ideas of decomposition in programming.

Functions are not run in a program until they are invoked in a program.

In Python, functions are defined with the keyword def followed by the function name and any arguments it may have in parentheses (multiple arguments are separated by commas):

def function_name(argument 1, argument 2):
    <expression>

Characteristics of function

  • has a name

  • has parameters (0 or more)

  • has a doc-string (optional but recommended)

  • has a body


def successor( x ):
    """
    Input : x, is any integer
    Returns successor of integer
    """
    x = x + 1
    print('successor is', x)
    return x
successor(3)

In above program :

def - keyword

successor - name

x - parameter or arguments

"""
Input : x, is any integer
Returns successor of integer
"""

Doc-string

x = x + 1
print('successor is', x)
return x

body

successor(3)

Later, in this code function is invoked using its name and value for parameters

Built-in Functions

Python provides a number of important built-in functions that we can use without needing to provide the function definition. The creators of Python wrote a set of functions to solve common problems and included them in Python for us to use.

Things like print(), input(), type() etc are all build in functions. One such function is max() and min().

The max and min functions give us the largest and smallest values in a list, respectively:

>>> max('Hello world')
'w'
>>> min('Hello world')
' '
>>>

The max function tells us the “largest character” in the string (which turns out to be the letter “w”) and the min function shows us the smallest character (which turns out to be a space).

Another very common built-in function is the len function which tells us how many items are in its argument.

>>> len('Hello world')
11
>>>

These functions are not limited to looking at strings.

Function Arguments in Python

Python provides a flexible way to define functions, allowing you to pass arguments to them. Function arguments enable you to pass values and data to functions, allowing for code reuse and modularity

Positional Arguments

The most common type of function arguments in Python is positional arguments. These arguments are passed to a function based on their position or order. When defining a function, you specify the parameters that it expects, and when calling the function, you provide the corresponding values in the same order.

Here's an example to illustrate positional arguments:

def greet(name, message): 
    print("Hello", name, message) 
greet("Aayush", "How are you?")

In the above code, the greet function takes two positional arguments: name and message. When calling the greet function, we pass the values "John" and "How are you?" in the same order as the parameters are defined.

The output of the above code will be:

Hello Aayush How are you?

Positional arguments are simple to use but require careful attention to the order of arguments.

Keyword Arguments

Keyword arguments, also known as named arguments, allow you to pass arguments to a function by explicitly specifying the parameter names along with their values. This way, you don't have to worry about the order of arguments.

Let's modify our previous example to use keyword arguments:

def greet(name, message):
    print("Hello", name, message) 

greet(message="How are you?", name="Aayush")

In the above code, we pass the values to the greet function using keyword arguments. The parameter names name and message are explicitly mentioned along with their corresponding values.

The output of the above code will be:

Hello Aayush How are you?

Keyword arguments offer more clarity and readability to the function calls, especially when dealing with functions that have a large number of parameters.

Default Arguments

Python allows you to assign default values to function parameters. These default values are used when the corresponding argument is not provided during the function call.

Consider the following example:

def greet(name, message="Hello"):
    print(message,name) 

greet("Aayush")
greet("Priya", "Hi")

In the above code, the greet function has a default argument message set to "Hello". When we call the function without providing a value for message, it uses the default value. However, if we provide a value for message, it overrides the default value.

The output of the above code will be:

Hello Aayush!
Hi Priya!

Default arguments are useful when you want to provide a common value for a parameter but allow the flexibility to override it when necessary.

return

The return function returns the value it is given (in this case, from a function). It differs from print() in that print() displays values while return returns values that can be used. For example:

def add_this(number_1, number_2):
    total = number_1 + number_2
    print(total)
some_variable = add_this(3, 8)

When the function add_this is called (when some_variable is defined), it will print 13 to the console but return the value None to some_variable (functions will return None if they don’t contain a return() statement). some_variable will then be equal to None even though add_this added 3 and 8 printed 11

def add_this(number_1, number_2):
    total = number_1 + number_2
    return total

In the above example, however, when the function add_this is called (when some_variable is defined), it will not print any value but return the value 11 to some_variable. some_variable will then be equal to 11 even though add_this didn’t print anything.

  • Unlike print(), return doesn’t require parentheses when called.

Also, the return statement can be used to return multiple values (by separating each of the additional return values with a comma):

return num, total, result

Scoping

A function’s scope describes the range of a function (what it can or can’t do). Any variables or parameters that are created inside a function are local, which means they only exist inside the function.

Once the function ends, those variables and parameters are destroyed, and cannot be called in the global scope (the world outside of a function, where regular variables are created). Because of this, functions can access variables outside (in the global scope), but cannot modify those variables in the global scope.

x = 10

def my_function(arg_1):
    x = 3
    print(x + arg_1)
    return x

In the above example, x = 10 is defined in the global frame. The function my_function creates a local variable also named x, but equal to 3 instead. my_function prints the sum of the local variable x (which is 3) added to the parameter arg_1, and then returns the value of the local variable x (which is 3). Once my_function is finished running, calling the variable x will invoke the variable x from the global frame (which is 10). The local variable x that was equal to 3 only existed within my_function and was destroyed once my_function ended.

x = 10

def my_function(arg_1):
    print(x)

The above function will print 10 if called, since no local value of x is defined and therefore my_function accesses the global variable x.

x = 10

def my_function(arg_1):
    x = x + 5

The above function cannot access the value of x in the global frame, because if so would be changing the value of the global variable x—something beyond the scope of a function. Since there has been no local variable named x that has been defined within the function, the above function will output an error.

docstring

To make code easier to read and understand, functions traditionally include a docstring that specifies the assumptions (the conditions that the function assumes are met in order to run) and guarantees (the conditions that the function will meet if all of its assumptions are met) of the function. Docstrings are written as multi-line comments, which are written inside two sets of three double quotes:

def my_function(arg1, arg2):
    """
    This is the docstring.
    It specifies the assumptions of this function…
    and the guarantees of it, too!
    """
    <expression>

Giving the built-in function help() any function name as an argument (e.g. help(my_function)) will display the name, arguments, and docstring of that function.

Liked this article. Follow me on twitter 🐦