Code前端首页关于Code前端联系我们

Python函数式编程,就看这篇文章吧!

terry 2年前 (2023-09-24) 阅读数 54 #后端开发

Python 函数式编程,看这一篇就够了!

Python 函数式编程,看这一篇就够了!

一流函数

在Python中,函数是“一流的”(first-class)。也就是说,函数与其他数据类型(例如 int)是同等的。

因此,我们可以将函数赋值给变量,将它们作为参数传递给其他函数,将它们存储在其他数据结构(例如字典)中,并将它们用作其他函数的返回值。

将函数视为对象

由于其他数据类型(例如 string、list 和 int)都是对象,因此 Python 中函数也是对象。让我们看一下示例函数 foo,它打印自己的名称:

def foo:
print("foo")

由于函数是对象,因此我们可以将函数 foo 分配给任何变量,然后调用该变量。例如,我们可以将函数赋给变量 bar:

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

语句 line = foo 将函数 foo 引用的对象赋给变量 bar。

将对象视为函数

当对象可以被调用时,它们就和函数一样,一样是对象。这是通过 __call__ 方法实现的。

示例如下:

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

每次配置Greeter类的对象时,我们都会创建一个新的对象,一个打招呼时可以喊出来的新名字。如下图:

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

我们之所以能够调用morning对象,是因为我们在类定义中使用了__call__方法。为了检查一个对象是否可以被调用,我们使用可调用的内置函数:

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

数据结构内部的函数

与其他对象一样,函数可以存储在数据结构内部。例如,我们可以创建一个int到func的字典。当 int 是要执行的步骤的简写时,这很方便。

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

以同样的方式,函数可以存储在许多其他数据结构中。

使用函数作为参数和返回值

函数也可以用作其他函数的参数和返回值。接受函数作为输入或返回函数的函数称为高阶函数,它们是函数式编程的重要组成部分。

高阶函数具有强大的属性。正如《Eloquent JavaScript》中所解释的:

“高阶函数允许我们对动作进行抽象,而不仅仅是抽象值。”

让我们看一个例子。假设我们想要迭代一个元素列表并按顺序打印它们。我们可以轻松构建一个重复函数:

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

它看起来很酷,但它只是一个第一级抽象。如果我们想在迭代列表时执行打印以外的操作怎么办?

这就是高阶函数存在的意义。我们可以创建一个函数 iterate_custom,其中要迭代的列表和应用于每个元素的函数是 iterate_custom 函数的输入:

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

这可能看起来微不足道,但实际上非常强大。

我们将抽象级别提高了一级,使代码更具可重用性。现在,我们不仅可以在打印列表时调用此函数,还可以对列表执行涉及序列迭代的任意操作。

功能还可以返回,让事情变得更加简单。就像我们将函数存储在dict中一样,我们也可以使用函数作为控制语句来确定合适的函数。例如:

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.

嵌套函数

函数也可以位于其他函数内部。这是一个“内部函数”。当您创建辅助函数(用作支持主函数的子模块的小型可重用函数)时,内部函数非常有用。

当问题需要特定的函数定义(参数类型或顺序)时,我们可以使用辅助函数。这种非传统方法使问题解决变得更加简单,例如:http://www-inst.eecs.berkeley.edu/~cs61a/sp12/lectures/lect4-2x3.pdf。

假设你要定义一个斐波那契函数 fib(n),它只有一个参数 n,我们需要返回第 n 个斐波那契数。

定义此类函数的一种可能方法是使用辅助函数来跟踪斐波那契数列的前两项(因为斐波那契数是前两个数的总和)。

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)

把这个计算从函数体移到函数参数中,非常强大。因为它减少了递归方法中可能发生的冗余计算。

单表达式函数(lambda表达式)

如果我们想编写一个函数而不给它命名怎么办?如果我们想编写一个简短的单行函数(例如上例中的函数 foo 或 mult)怎么办?

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

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

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

注意:lambda函数必须是单行,并且不能包含程序员编写的return语句。

事实上,它们通常有一个隐式的 return 语句(在上面的例子中,函数会说 return x * y,但我们在 lambda 函数中省略了显式的 return 语句)。

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对象类型转换为列表。现在,我们不再显式定义multiply_by_four函数,而是定义一个lambda表达式:

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

当我们想要对集合中的所有值执行操作时,map函数非常有用。

过滤

顾名思义,过滤功能有助于过滤掉不需要的项目。如果我们例如想要去除分数中的奇数,那么我们可以使用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提供的函数有两个参数:一个代表正在检查的元素,另一个代表所应用操作的累积结果。

  • 在 Python 中使用函数式编程的最佳实践:https://kite.com/blog/python/function-programming/
  • 函数式编程室和注释:❀arhttps://www.hackershttps: //万维网。 .com/zh/practice/python/function-programming/function-programming-1/tutorial/

原始链接:https://medium.com/better-programming/introduction-to-function-programming- in-python-3d26cd9cbfd7

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门