skip to content
Ratul's Blog

Basic functional programming in Python

// And why the func should you care?!



What is a function?

A function is a block of code that is executed when it is called. It can take parameters and return a value. It is a way to create reusable code.

Why use functions?

Functions are useful for creating reusable code. They can be used to perform a specific task. They can also be used to perform a specific task multiple times or to perform a specific task multiple times with different parameters.

Built-in functions

Python has a number of built-in functions. These are functions that are already defined in the Python language. They can be used without having to define them. Some of the most common built-in functions are:

  • print() which prints it’s arguments to the screen,
  • input() which takes input from the user,
  • len() which returns the length of an object,
  • type() which returns the type of an object, and many others.

User-defined functions

User-defined or ‘regular’ functions in python are custom functions which we can create with the def keyword.

Arguments and return values

User-defined functions can take arguments and return values. The return keyword is used to return a value from a function. If no value is returned, the function returns None. The return keyword can also be used to exit a function early.

# Example of arguments and return values

def add(a, b): # a and b are called arguments
    c = a + b
    return c # c is called a return value

Calling a function

To call a function, you use the function name followed by parentheses. The parentheses can contain arguments to pass to the function. The arguments are separated by commas. The order of the arguments matters.

# Example of calling a function

add(1, 2) # returns 3

We can also store the return value of a function in a variable to use later.

# Example of storing the return value of a function in a variable

result = add(1, 2)
print(result) # prints 3

Docstrings

Docstrings are used to document functions. They are defined by a string literal that is the first statement in the function. They are also used by the help() function to display documentation for a function.

# Example of a docstring

def add(a, b):
    """Adds two numbers together"""
    c = a + b
    return c

Type annotations

Type annotations are used to specify the type of arguments and return values. They are defined by a colon followed by the type. They are not enforced by the Python interpreter, but they can be used by other tools (e.g. pydantic).

# Example of type annotations

def add(a: int, b: int) -> int:
    c = a + b
    return c

The example above takes two integers and returns an integer.

Default arguments

Default arguments are used to specify a default value for an argument. If the argument is not passed to the function, the default value is used instead. Default arguments must be defined after all non-default arguments.

# Example of default arguments

def add(a, b, c=0):
    d = a + b + c
    return d

add(1, 2) # returns 3
add(1, 2, 3) # returns 6

Arbitrary arguments (args)

Arbitrary arguments are used to pass a variable number of arguments to a function. They are defined by an asterisk (*) followed by the name of the argument. The arguments are passed to the function as a tuple.

# Example of arbitrary arguments

def add(*args):
    total = 0
    for arg in args:
        total += arg
    return total

add(1, 2, 3) # returns 6

Keyword arguments (kwargs)

Keyword arguments are used to pass a variable number of keyword arguments to a function. They are defined by two asterisks (**) followed by the name of the argument. The arguments are passed to the function as a dictionary.

# Example of keyword arguments

def add(**kwargs):
    total = 0
    for key, value in kwargs.items():
        total += value
    return total

add(a=1, b=2, c=3) # returns 6

Lamda functions

Lambda functions are anonymous functions (no named identifier) that can be used to create a function on the fly. They are useful when you need to pass a function as an argument to another function. They are defined with the lambda keyword followed by the arguments, a colon, and the expression to return.

# Example of a lambda function

# a,b are the arguments, a + b is the expression to return
add = lambda a, b: a + b 

add(1, 2) # returns 3

Lamda functions in pandas

Lamda functions are useful when used with pandas. They can be used to create new columns in a dataframe.

# Example of using a lambda function to create a new column in a dataframe

# Import pandas
import pandas as pd

# Create a dataframe 
df = pd.DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6]
})

# Create a new column with the sum of a and b
df["c"] = df.apply(lambda row: row["a"] + row["b"], axis=1)

Decorator functions

Decorator functions are used to modify the behavior of other functions. They are defined with the @ symbol followed by the name of the decorator function. The decorator function must take a function as an argument and return a function.

# Example of a decorator function

def decorator(func):
    def wrapper(*args, **kwargs):
        print("Before")
        func(*args, **kwargs)
        print("After")
    return wrapper

@decorator
def add(a, b):
    print(a + b)

add(1, 2)

A common use case for decorators is to determine the execution time of a function. Here is an example of a timer:

# Example of a decorator function that times a function

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print(f"Time taken: {end - start}")
    return wrapper

@timer
def add(a, b):
    print(a + b)

add(1, 2)

Recursive functions

Recursive functions are functions that call themselves. They are useful for performing a task multiple times. They are defined with the def keyword followed by the name of the function, the arguments, a colon, and the expression to return. The expression to return must call the function again with different arguments.

# Example of a recursive function

def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)

factorial(5) # returns 120

I would be careful with these as they can cause infinite loops if not used correctly.

Exercises

You can find some exercises to practice your python skills here and here.

Thanks for reading! 🫶

I would love to hear your thoughts on this. If you have any questions or comments, please feel free to reach out on any of the platforms below. I look forward to connecting with you!