This article is participating in Python Theme Month. See the link to the event for more details

Functional programming is a little less popular now, but there are still a lot of people talking about it. Functional programming is not anything new, was put forward in very early, so once again back to our eyes become hot spot, is also a natural thing, because today’s program is more and more complex, to facilitate the expansion and testing, functional programming is particularly important at this moment, because functional programming for the same input output is certain. In order to reduce the cost we need to separate the certain from the uncertain. For the internal application we only need to do a good job of the certain, and do not have to worry too much about the uncertain. In life, too, we do what we can.

So what is functional programming, whether the Python language supports functional programming, and how to apply functional programming to scientific research. These are some of the topics that we’re going to talk about today.

What is functional programming

Sometimes I don’t like to use one concept to explain another. So what is the function? F of x is equal to 2xf of x is equal to 2xf of x is equal to 2x. This is a simple function, which in its own way is a mapping between two sets. Functional programming can be thought of as a unit of computation

  • Functional programming is a style of programming
  • Lambda Calulus can be used to explain functional programming

History of functional programming

  • John McCarthy invented LISP as an early support
  • John Backus defined functional programming back in 1977

What are the styles of functional programming

  • Invariance (no side effect)
  • Function composition
  • stateless
  • concurrent

Functional programming is embracing data science

  • Functional programming is more suitable for ELT
  • Moreover, functional programming provides high reuse of the cell

Data is immutable

We all want things or people to remain the same. If we like someone, we will stay the same forever. But the reality is often counterproductive, but I believe there is still such a simple and pure love.

Python’s support for immutable data

s = "hello"
s + "wolrd"
s # hello
Copy the code

Numpy’s support for immutable data

import numpy as np
a = np.array([2.3.4.5])
a.append(0)
Copy the code

Numpy, a database widely used in data science, also has good support for functional programming features of immutable data. For example, once the numpy array has been created, we cannot add new elements to the array. AttributeError: ‘numpy. Ndarray ‘object has no attribute’ Append ‘. This stems from the implementation design of NUMPY,

a[0] = 1
a # array([1, 3, 4, 5])
Copy the code

Not when we set ndarray as follows

a.flags.writeable = False
Copy the code

ValueError: Assignment Destination is read-only This exception may not be formed inside a[0]=1 after setting A.lags. Writeable = False. So if you want to modify this ndarray, you need to assign a copy of it with the copy command.

Pandas’ support for immutability

By default, inplace=False, which means that changes to the DataFrame will not reflect the existing data. Instead, it generates a new DataFrame based on the modification. This shows that Pandas is also good at immutable.

tut_dictionory = {
    'name': ['basic machinelearning'.'deep learning'.'efficient python programming'].'price': ['120.0'.'300.0'.None].'level': [0.1.2]
}
df = pd.DataFrame(tut_dictionory)
df.head()
Copy the code
  • df.replace(inplace=True)
  • df.dropna(inplace=True)
  • df.drop(inplace=True)
  • df.rename(inplace=True)
  • df.fillna(inplace=True)

Pure functions

First of all, a pure function, a pure function is a function that takes the same parameters and always returns the same result, no side effects, so you can understand a function mathematically. To understand what a pure function is, everything else is easy to understand, but what is a side effect is relatively hard to understand, so I’m going to focus on what is a side effect, and I think once you understand what a side effect is, you’ll understand what a pure function is.

What are the Side effects?

For those of you who don’t know what side effects are, let’s take a small example, and then list what are side effects

global_list = []

def non_pure_add1_func(x) :
    global_list.append(x)
    return x+1
Copy the code

In this simple but illustrable example, the non_pure_add1_func function updates the global variables in addition to returning x +1 as function output. So we need to keep the pure function from doing things like updating global state, or I/O.

Side effects include

  • Any I/O operation (network, file system, INPUT/output devices)
  • An exception is thrown
  • Update object state
  • Update global Status

Pure functions

We understand what side effects are, and we understand what pure functions are. So why do we need a pure function, and what benefits does it give us? First of all, pure functions are intuitive and deterministic, and new pure functions can be obtained by random combination, which is easy to test and cache, and easy to parallel calculation, because each function is independent and does not involve data consistency or update state problems.

combination
def add(a,b) :
    return a + b
def subtract(x,y) :
    return add(x,y *-1)
Copy the code

Referential transparency

Function composition

  • Higher-order functions
  • The function is the first citizen

Declarative and declarative

  • Imperative tells the program what to do and also tells the program how to do it. Okay
  • Declarative just tells the program what to do, okay

Let’s say the matrix dot product

Imperative implementation

A = [[1, -1.2], [0.3.1]]
x = [2.1.0]
result = []
row_count = 0
for row in A:
    partial_result = 0
    for i in range(len(row)):
        a_elem = row[i]
        x_elem = x[i]
        partial_result += (a_elem * x_elem)
    result.append(partial_result)
    row_count += 1
    
result
Copy the code

Functional implementation

A_arr = np.array([[1, -1.2], [0.3.1]])
x_arr = np.array([2.1.0])
A_arr @ x_arr

Copy the code

Map, Filter, and Reduce

When it comes to numpy arrays, there are three methods (Map, Filter, and Reduce) that help you understand the functional programming style. I’ll discuss each of these methods and see how they can be used in Python as well as numpy.

Map

The Map will operate or transform each of the elements of the set, and the elements that operate or transform will form a new set.

items = [1.2.3.4.5]
squared = list(map(lambda x: x**2, items))
Copy the code

In NUMpy, it’s much easier to map with a list, and just need items**2 to manipulate each element.

items = np.array([1.2.3.4.5])
items**2
Copy the code

Filter

Filter creates a list of elements, one of which operates on each element with a bool value, and true keeps that element in the new list.

number_list = range(-5.5)
less_than_zero = list(filter(lambda x: x < 0, number_list))
Copy the code
number_list_arr = np.array(range(-5.5))
number_list_arr[number_list_arr>0] # array([1, 2, 3, 4])
Copy the code

Reduce

Reduce is a very useful function that performs some calculation on a list and returns the result. To add up by constantly settling on the basis of the previous calculation. Redux in JS seems to be based on reduce implementation.

from functools import reduce
product = reduce((lambda x, y: x * y), [1.2.3.4])
Copy the code
np.multiply.reduce([2.3.5])
Copy the code