Analytics Vidhya

Analytics Vidhya is a community of Generative AI and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com

Follow publication

Functional Programming with Python

--

What is functional programming?

Functional programming languages are specially designed to handle symbolic computation and list processing applications. Functional programming is based on mathematical functions. Some of the popular functional programming languages include: Lisp, Python, Erlang, Haskell, Clojure, etc.

Recently, the use of functional programming has been on the rise. Thus, many traditionally imperative languages like Java and Python have started to support functional programming techniques. In this article I will be introducing some of these techniques to you with assuming you have basic understanding of functional programming. if you are not familiar with basic function programming, check this article on function programming.

First-Class Functions

Python functions are first class objects. Thus, we can assign them to variables, pass them as arguments to other functions, store them in other data structures such as dictionaries and use them as return values for other functions.

In the example below, we are assigning function to a variable. This assignment doesn’t call the function. It takes the function object referenced by shout and creates a second name pointing to it, Tell.

def Show(Text):    return Text.upper()print(Show("Hello World"))Tell = Showprint(Tell("Hello World"))OUTPUT
HELLO WORLD
HELLO WORLD

Since functions are objects, we can assign the function Show to any variable and then call that variable to refer to the function. For example, we can assign it to the variable Tell.

Functions inside data structures

Same as other objects, Functions can also be stored inside Data Structures. For example, we can create a dictionary with mapping of int to func. This is useful for when the int is a shorthand for a procedure to be performed.

#INITIALIZING DICTIONARY
dict = {
0: func1,
1: func2
}
x = input() #GET INTEGER VALUE FROM USER
dict[x]() #CALL THE FUNCTION RETURNED BY DICTIONARY ACCESS

Functions as arguments and return values

A function can take multiple arguments, these arguments can be objects, variables(of same or different data types) and functions.

Functions can also serve as arguments and return values of other functions. The functions that either accept or return functions are known as higher-order functions and are an important part of functional programming.

Higher-order functions are extremely powerful. As explained deeply on Eloquent JavaScript:

Consider an example.

Let’s say we want to iterate over a list of items and print them sequentially. We can easily build an iterate function:

def iterate(list_of_items):
for item in list_of_items:
print(item)

This might seem cool, but this is just one level of abstraction. What if we want to do something different (instead of print) when we iterate over the list?

That’s where higher-order functions come in. We can create a function iterate_custom that takes in both a list to iterate and a function to be applied on each item:

def iterate_custom(list_of_items, custom_func):
for item in list_of_items:
custom_func(item)

Although this might seem trivial, it is immensely powerful.

We’ve moved up a layer of abstraction and made our code more reusable. Now, we can call the function not only when we want to print a list, but also do anything with the list that involves sequential iteration.

Functions can also be returned to make things simpler. Just like how we stored functions in a dict, we can also use a function as control flow to decide the appropriate function. For example:

def add(x, y):
return x + ydef sub(x, y):
return x - ydef mult(x, y):
return x * ydef calculator(opcode):
if opcode == 1:
return add
elif opcode == 2:
return sub
else:
return mult my_calc = calculator(2) #MY CALC IS A SUBSTRACOTR
my_calc(5, 4) #RETURNS 5 - 4 = 1
my_calc = calculator(9) #MY CALC IS A MULTIPLLIER
my_calc(5, 4) #returns 5 x 4 = 20.

Nested functions

Functions can be defined inside of other functions as well and these are aptly called inner functions. These are especially useful to make helper functions — small, reusable functions that support the main function as a sub-module.

Helper functions are handy when a problem requires a specific function definition (argument type or order) but it is easier to solve the problem without following the convention. A good example is from this lecture slide.

Let’s say you want to define a fibonacci function, fib(n), which takes a single argument, n, and we have to return the nth fibonacci number.

A possible way of defining such a function is with the use of a helper function that tracks the previous two terms of the fibonacci sequence (since a fibonacci number is simply the sum of the previous two fibonacci numbers).

def fib(n):
def fib_helper(fk1, fk, k):
if n == k:
return fk
else:
return fib_helper(fk, fk1+fk, k+1) if n <= 1:
return n
else:
return fib_helper(0, 1, 1)

Moving the calculation from function body to function argument is incredibly powerful because it reduces redundant calculation that may occur in a recursive approach.

Lambda Expressions (Single Expression Functions)

How can we define a function without giving it any name? We can apply lambda function to define short and on -liner functions for example shown below.

add = lambda x, y: x + y
add(1, 2) #RETURNS 2

The behavior of this add is exactly the same as the one defined using the traditional def keyword earlier.

Note that lambda functions must be one-liners and must not contain a return statement written by the programmer.

In-fact, they always have an implicit return statement (in the above example, it would say return x + y but we omit explicit return statements from lambda functions).

The lambda function is much more powerful and concise because we can also construct anonymous functions — functions without a name:

(lambda x, y: x * y)(9, 10) #RETURNS 90

This is a handy method for whenever we need a function only once and need not use it later. For example, when filling up a dictionary:

import collections
pre_fill = collections.defaultdict(lambda: (0, 0))
#all dictionary keys and values are set to 0

We can now look at Map, Filter, and Reduce to appreciate lambda even more.

Map, Filter, and Reduce

1. Map

map is a function that takes a set of inputs and transforms them into another set based on a function specified. This is same as the iterate_custom function . For example:

def substract_1(x):    return x - 1
scores = [10, 9, 8, 7, 6, 5]
new_scores = list(map(substract_1, scores))
#NEW SCORES ARE NOW [9, 8, 7, 6, 5, 4]
print(new_scores)

In Python 3, the map function returns a map object that can be typecast to a list for us to make use of it. Now, instead of defining the multiply_by_four function explicitly, we can define a lambda expression:

new_scores = list(map(lambda x: X-4, scores))

2. Filter

filter, as the name suggests, is a function that helps “filter” out unwanted items. For example, we may want to filter out all the odd numbers from scores. We can do so using filter:

even_scores = list(filter(lambda x: (x % 2 == 0), scores))
#even_scores = [6, 8]

Since the function supplied to filter decides the acceptance of an item on a case-by-case basis, the function must return a bool value (as seen in the lambda function above) and must be unary (take one input parameter).

3. Reduce

reduce is a function to “summarize” or to get a “big-picture” of a set of data. For example, if we want to calculate the sum of all scores, we can use reduce:

sum_scores = reduce((lambda x, y: x + y), scores)
#sum_scores = 32

This is much simpler than writing a loop. Note that the function supplied to reduce requires two params: one represents the current item being inspected and one is the cumulative result of the operation being applied.

Note that the above just gets you started, although thoroughly, with functional programming in Python.

Moreover, You can practice and explore these concepts on this hacker-rank module.

Thank you for Reading and consider clap if you find it useful.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Analytics Vidhya
Analytics Vidhya

Published in Analytics Vidhya

Analytics Vidhya is a community of Generative AI and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com

Neel Gorasiya
Neel Gorasiya

Written by Neel Gorasiya

Software Engineer | Javascript/Typescript | MERN Stack developer

Responses (1)

Write a response