Home  >  Article  >  Backend Development  >  Detailed article on Python functional programming techniques

Detailed article on Python functional programming techniques

王林
王林forward
2023-04-13 15:16:071226browse

This article provides a simple introduction to functional programming technology in Python.

Detailed article on Python functional programming techniques

First-class functions

In Python, functions are "first-class citizens". That is, functions are on an equal footing with other data types such as int.

Thus, we can assign functions to variables, pass them as arguments to other functions, store them in other data structures (such as dicts), and use them as return values ​​​​of other functions.

Treat functions as objects

Since other data types (such as string, list, and int) are objects, functions are also objects in Python. Let's look at the example function foo, which prints its own name:

def foo():
 print("foo")

Since functions are objects, we can assign function foo to any variable and then call that variable. For example, we can assign a function to the variable bar:

bar = foo
bar()
#will print "foo" to the console

The statement bar = foo assigns the object referenced by the function foo to the variable bar.

Treat objects as functions

When objects are callable, they are the same as functions, such as object(). This is achieved through the call method.

The example is as follows:

class Greeter:
 def __init__(self, greeting):
self.greeting = greeting
 def __call__(self, name):
return self.greeting + " " + name

Every time we configure an object of the Greeter class, we will create a new object, which is a new name that can be shouted when greeting. As shown below:

morning = Greeter("good morning") #creates the callable object
morning("john") # calling the object
#prints "good morning john" to the console

The reason why we can call the morning object is that we have used the call method in the class definition. To check if an object is callable, we use the built-in function callable:

callable(morning) #true
callable(145) #false. int is not callable.

Functions inside data structures

Functions, like other objects, can be stored inside data structures. For example, we can create a dictionary of int to func. This comes in handy when an int is a shorthand for the step to be performed.

# store in dictionary
mapping = {
 0 : foo,
 1 : bar
}
x = input() #get integer value from user
mapping[x]() #call the func returned by dictionary access

Similarly, functions can be stored in a variety of other data structures.

Using functions as parameters and return values

Functions can also be used as parameters and return values ​​of other functions. Functions that accept functions as input or return functions are called higher-order functions, and they are an important part of functional programming.

Higher-order functions have powerful capabilities. As explained in "Eloquent JavaScript":

"Higher-order functions allow us to abstract actions, not just abstract values."

Let's look at an example. Suppose we want to iterate over a list of items and print them out in sequence. We can easily build an iterate function:

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

It looks cool, but it's just a first-level abstraction. What if we want to do something other than print while iterating over the list?

This is the meaning of the existence of higher-order functions. We can create a function iterate_custom, where the list to be iterated over and the function to be applied to each item are the inputs to the iterate_custom function:

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

This may seem trivial, but it is actually very powerful.

We have raised the level of abstraction to make the code more reusable. Now, not only can we call this function when printing a list, we can also perform arbitrary operations on the list involving sequence iteration.

Functions can also be returned, making things even simpler. Just like we store functions in dict, we can also use functions as control statements to determine the appropriate function. For example:

def add(x, y):
return x + y
def sub(x, y):
return x - y
def mult(x, y):
return x * y
def calculator(opcode):
if opcode == 1:
 return add
elif opcode == 2:
 return sub
else:
 return mult 
my_calc = calculator(2) #my calc is a subtractor
my_calc(5, 4) #returns 5 - 4 = 1 
my_calc = calculator(9) #my calc is now a multiplier
my_calc(5, 4) #returns 5 x 4 = 20.

Nested functions

Functions can also be inside other functions. This is an "internal function". Intrinsic functions are useful when creating helper functions, small reusable functions that serve as submodules to support the main function.

We can use auxiliary functions when the problem requires a specific function definition (parameter type or order). This non-traditional approach makes problem solving much simpler, for an example see:

http://www-inst.eecs.berkeley.edu/~cs61a/sp12/lectures/lect4-2x3. pdf.

Suppose you want to define a Fibonacci function fib(n), which has only one parameter n, and we must return the nth Fibonacci number.

One possible way to define such a function is to use a helper function to track the first two terms of the Fibonacci sequence (since the Fibonacci number is the sum of the first two 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)

Move the calculation from the function body to the function parameters, which is very powerful. Because it reduces redundant calculations that may occur in recursive methods.

Single expression function (Lambda expression)

What should we do if we want to write a function before giving the function a name? What if we want to write a short one-line function (such as function foo or mult in the example above)?

我们可以在 Python 中使用 lambda 关键字来定义此类函数。示例如下:

mult = lambda x, y: x * y
mult(1, 2) #returns 2

该 mult 函数的行为与使用传统 def 关键字定义函数的行为相同。

注意:lambda 函数必须为单行,且不能包含程序员写的返回语句。

事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 return x * y,不过我们省略了 lambda 函数中的显式返回语句)。

lambda 函数更加强大和精准,因为我们还可以构建匿名函数(即没有名称的函数):

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

当我们只需要一次性使用某函数时,这种方法非常方便。例如,当我们想填充字典时:

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

接下来我们来看 Map、Filter 和 Reduce,以更多地了解 lambda。

Map、Filter 和 Reduce

Map

map 函数基于指定过程(函数)将输入集转换为另一个集合。这类似于上文提到的 iterate_custom 函数。例如:

def multiply_by_four(x):
return x * 4
scores = [3, 6, 8, 3, 5, 7]
modified_scores = list(map(multiply_by_four, scores))
#modified scores is now [12, 24, 32, 12, 20, 28]

在 Python 3 中,map 函数返回的 map 对象可被类型转换为 list,以方便使用。现在,我们无需显式地定义 multiply_by_four 函数,而是定义 lambda 表达式:

modified_scores = list(map(lambda x: 4 * x, scores))

当我们想对集合内的所有值执行某项操作时,map 函数很有用。

Filter

就像名称所显示的那样,filter 函数可以帮助筛除不想要的项。例如,我们想要去除 scores 中的奇数,那么我们可以使用 filter:

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

由于提供给 filter 的函数是逐个决定是否接受每一个项的,因此该函数必须返回 bool 值,且该函数必须是一元函数(即只使用一个输入参数)。

Reduce

reduce 函数用于「总结」或「概述」数据集。例如,如果我们想要计算所有分数的总和,就可以使用 reduce:

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

这要比写循环语句简单多了。注意:提供给 reduce 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。

The above is the detailed content of Detailed article on Python functional programming techniques. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:51cto.com. If there is any infringement, please contact admin@php.cn delete