This article introduces functional programming. Three major higher-order functions will be introduced in this article, starting with basic examples of functional programming.

The map ()

Map means mapping. In mathematical learning, mapping is the relationship between X and y, that is, x is called Y by certain methods. Let’s start with an example that doubles the number of elements in the array [1,2,3,4,5,6,7,8].

At first glance, it looks simple, and can be solved through a simple loop. So let’s first use this method to solve:

def num2(list):
    newList = []
    for x in list:
        x *= 2
        newList.append(x)
    return newList
Copy the code

Execution method:

Num2,2,3,4,5,6,7,8 list = [1] (list)Copy the code

The output is:

,4,9,16,25,36,49,64 [1]Copy the code

The above method is an integer, if it is extended to a character or string, let’s look at another example – case conversion.

For simplicity, we just convert [‘a’,’b’,’c’,’d’] to [‘a’,’b’,’c’,’d’]

def upperNum(list):
    newList = []
    for x in list:
        newList.append(x[:].upper())
    return newList
Copy the code

Execute function:

list = ['a','b','c','d']
print upperNum(list)
Copy the code

The output is:

['A', 'B', 'C', 'D']
Copy the code

Do you see any similarities between these two examples? All elements in an array are transformed by some method, the only difference being the type and method of the array passed in. So, can we define this similarity function, pass in an array and a method.

Fortunately, generics are very simple in Python, which allows us to ignore the types of variables in arrays. The discussion of generics is covered in the sidebar below, and will be familiar if you are familiar with other programming languages.

And how you pass functions in as arguments is functional programming.

Functional programming is a programming paradigm with a high degree of abstraction. Functions written in pure functional programming languages have no variables. Therefore, as long as the input of any function is determined, the output is determined, and this pure function is called no side effects. While allowing the use of variables in programming languages, because of the variable state of the function is uncertain, the same input, may get different output, therefore, this function is a side effect.

Python provides partial support for functional programming, which can either be passed as arguments or return a function. Because Python allows the use of variables, Python is not a purely functional programming language.

Let’s define a map function whose parameters are function method and sequence array, and find that its return value is still an array.

def map(function,sequence):
    newList = []
    for x in sequence:
        newList.append(function(x))
    return newList
Copy the code

These two can be combined using the map method:

def num2(x):
  return x * x

def upperNum(x):
    return x[:].upper()

map(num2,list)
map(upperNum,list)
Copy the code

The execution result is still:

[1,4,9,16,25,36,49,64] ['A, 'B, 'C, 'D']Copy the code

Note that in python2 it is possible to return the result directly, but in python3 it returns an object. To use the result, you must add a list in front of it to convert it, for example:

The map function in the system library is defined as follows, with an optional parameter:

map(function, sequence, *sequence_1)
Copy the code

If multiple sequences are given, the function is called, containing the items for each sequence of the corresponding argument list; When not all, None is used to replace the missing value so that the length of the sequence is the same. If the function does not, returns the items of a list sequence (or an array list, if more than one sequence).

Such as:

l1 = [ 0, 1, 2, 3, 4, 5, 6 ]
l2 = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
map(f, l1, l2)
Copy the code

The result is:

[(0, 'Sun'), (1, 'Mon'), (2, 'Tue'), (3, 'Wed'), (4, 'Thu'), (5, 'Fri'), (6, 'Sat')]
Copy the code

The map method can still be further simplified by mentioning an anonymous function in the supplement.

The filter ()

A filter is a filter that filters out the elements in an array or primitive that meet the criteria. Let’s start with an example that picks an odd number from 1 to 10:

def is_Odd(list):
    newList = []
    for x in list:
        if x%2 :
            newList.append(x)
        else:
            pass
    return newList
Copy the code

Execute function:

,2,3,4,5,6,7,8,9 list = [1] is_Odd (list)Copy the code

The output is:

[1, 3, 5, 7, 9]
Copy the code

For another example, suppose we have an array string array exampleFiles that marks a file path and assigns the following value:

exampleFiles = ["README.md", "HelloWorld.py","HelloSwift.swift", "HelloPython.py"]
Copy the code

Now we want to take the.py array from the array, and use a loop to get:

def getPyFile(fileNames):
  newFileNames = []
  for fileName in fileNames:
      if ".py" in fileName:
         newFileNames.append(fileName)
  return newFileNames
Copy the code

Execute this function:

fileNames =  ["README.md", "HelloWorld.py","HelloSwift.swift", "HelloPython.py"]
getPyFile(fileNames)
Copy the code

The result is:

['HelloWorld.py', 'HelloPython.py']
Copy the code

From the above examples, you can see that the two methods have something in common, which is to return the sequence items that are true. If the function is None, return True and a list. (Return the same type if the sequence is a tuple or string)

So, with the foundation of the map function above, we can define a filter method that combines the above methods into one:

def filter(function,sequence):
    list = []
    for x in sequence:
        if function(x):
            list.append(x)
    return list
Copy the code

For example, to filter a file, execute this method:

def getPyFile2(fileName):
  if ".py" in fileName:
       return fileName
   else:
       pass

filter(getPyFile2,fileNames)
Copy the code

The result of executing this function is:

['HelloWorld.py', 'HelloPython.py']
Copy the code

Like map, the filter function in python3 returns an object that is converted to an array by adding a list.

Reduce ()

Reduce means aggregation. With the foundation of map and filter functions, let’s also discuss a simple function first. Define a function that computes the sum of all integers in an array.

The sum () function comes with the Python library, but we’ll use our own

def sum(list):
    result = 0
    for x in list:
        result += x
    return result
Copy the code

Execute function:

list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
sum(list)
Copy the code

The result is:

45
Copy the code

Here’s another example: take a group of words and put them together into a sentence. Such as array [” I “, “am”, “a”, “good”, “boy”] joining together into a string, “I am a good boy.” “

Define the function as follows:

def append(list):
    result = ""
    for x in list:
        result = result + x+" "
    return result
Copy the code

Execute function:

list = ["I","am","a","good","boy"]
append(list)
Copy the code

The result is:

"I am a good boy "
Copy the code

The above two functions are similar in that they both initialize the variable result with some value, and they both iterate through the array list and update the result with some algorithm. To define a generic function that implements this generic algorithm, two abstractions are required: the initial value of result and the function used to update the result value in each loop.

So we can define a function that satisfies the above requirements, noting that the reduce function returns a value instead of an array:

def reduce(function,sequence):
    result = None
    for x in sequence:
        result = function(result,x)
    return result
Copy the code

Function is the function to be operated on, sequence is an array, and the values of the elements in result and sequence are assigned to result for circular operation.

Performing the above function operations simplifies:

def sum(a,b):
    return  a + b

def append(a,b):
    return  a + " " + b

reduce(sum,list)
reduce(append,list)
Copy the code

This gives us the desired reduce function. Reduce in the system have been defined as the reduce (function, sequence, initial = None), due to the initial value is not only the zero or an empty string, can be arbitrary, so you need to assign initial values, here to give an initial variables and initial value by default. Adapt the reduce function as follows:

def reduce(function,sequence,initial=None):
    result = initial
    for x in sequence:
        result = function(result,x)
    return result
Copy the code

supplement

Anonymous functions

In Python, there is limited support for anonymous functions. To calculate f(x)=x2, define a function of f(x) and use the map function, for example:

def f(x):
  return x * x

list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
Copy the code

The output is:

[1, 4, 9, 16, 25, 36, 49, 64, 81]
Copy the code

Using anonymous functions, we can solve this with a single line:

list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
Copy the code

The output is also as follows:

[1, 4, 9, 16, 25, 36, 49, 64, 81]
Copy the code

As you can see from the example above, the anonymous function keyword is lambda, and the x before the colon represents the function argument. Anonymous functions have one limitation: they can only have one expression. Instead of writing a return, the return value is the result of that expression.

One advantage of using anonymous functions is that they don’t have names, so you don’t have to worry about function name conflicts. In addition, an anonymous function is also a function object. It is also possible to assign an anonymous function to a variable and use the variable to call the function, for example:

f = lambda x: x * x
f(5)
Copy the code

The result is:

25
Copy the code

Therefore, the above programs can be simplified by using anonymous functions:

filter(lambda fileName:".py" in fileName,fileNames)
reduce(lambda a, b: a + b,list)
reduce(lambda a, b: a + " " +b,list)
Copy the code

Sorted function

The sorted function, as its name suggests, is also easy to use.

sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
Copy the code

In the system, sort is defined as:

def sorted(iterable, cmp=None, key=None, reverse=False)
Copy the code

The higher order lies in the next three parameters. The reverse argument is a bool variable that is in reverse order and defaults to False (positive order). Key is the keyword and is the object used for sorting. In the previous example, it was the array itself, and of course it is possible to sort the ones digit of the array, as in:

sorted([36, 5, 12, 9, 21],key=lambda x:x%10)
[21, 12, 5, 36, 9]
Copy the code

The CMP parameter is a comparison method. If we want to implement reverse instead of reverse, we can write:

sorted([36, 5, -12, 9, -21],cmp=lambda x,y:cmp(x,y))
[-21, -12, 5, 9, 36]
Copy the code

practice

To end this article, I give you a small example to understand three functions. (Title from Functional Programming published by Objc.io)

A set of urban and demographic data is as follows:

name: "Paris", population: 2243
name: "Madrid", population: 3216
name: "Amsterdam", population: 811
name: "Berlin", population: 3397
Copy the code

Suppose we wanted to find cities with at least 1 million people and print out their names and populations. The output would be:

City: Population
Paris : 2243000
Madrid : 3216000
Berlin : 3397000
Copy the code

First we filter out cities with less than a million people. Then, map function is used for projection, and the units of urban population are converted. Finally, we use Reduce to compute a string from a list of city names and populations. Here we use the library’s Map, Filter, and Reduce functions. As a result, we can chain these functions together like a chain.