python进阶——函数(三)

本文最后更新于:1 年前

(四)函数式编程

Python是面向对象的程序设计语言,也是面向过程的程序语言,同时也支持函数式编程。

Pyhon标准库functools 提供了若干关于函数的函数,提供了Haskell和Standard ML中的函数式程序设计工具。

Python中的函数与其他数据类型处于平等地位,因此函数可以赋值给变量,可以作为参数传入其他函数,存储在其他数据结构中,或者作为函数的返回值。

1. 作为对象的函数:

函数在Python中是作为对象存在的,故函数对象可以赋值给变量,然后调用该变量。

1
2
3
4
def printself():
print("123321")
copyfun = printself
copyfun()

数据结构内的函数:函数作为对象,也可以存储数据结构内部。

1
2
3
4
5
6
7
8
9
10
def fun1():
print("fun1")
def fun2():
print("fun2")
def fun3():
print("fun3")
map_fun = {1:fun1,2:fun2,3:fun3}
map_fun[2]()
#运行结果:
# fun2

函数作为参数和返回值:函数可以作为其他函数的参数和返回值,接受函数作为输入或返回函数的函数叫做高阶函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def fun_use(fun,list_use):
return fun(list_use)
print(fun_use(max,[1,2,3,4,5,6,3.4,7.2]))
# 运行结果:
# 7.2

def add(a,b):
return a+b
def sub(a,b):
return a-b
def fun_high(x):
if x==1:
return add
elif x==2:
return sub
else:
return None
fun_use = fun_high(1)
print(fun_use(2,1))
fun_use = fun_high(2)
print(fun_use(2,1))
#运行结果:
# 3
# 1

函数名实际上也是变量,可以让函数名指向其他对象,但是这样会导致原有的函数无法使用。

1
2
3
4
5
6
def add(a,b):
return a+b
add =10
print(add)
#运行结果:
# 10

嵌套函数、Lambda表达式也是函数式编程的一部分,详见之前的博客,下面介绍更进一步的内容。

2. Map、Filter 和 Reduce:

(1) map函数:

map 函数的功能是对可迭代对象中的每个元素都调用指定的函数,并返回一个map对象的iterator迭代器(可以转化为list对象)。

语法格式:map(function, iterable)

function参数表示传入的函数,可以是内置函数、自定义函数或者 lambda 匿名函数,iterable表示可迭代对象,可以是列表、元组等,允许一到多个。

一般用于对某个集合对象的全部值执行某个特定操作。

map() 函数由 C 语言实现,执行效率高。

例子如下:

1
2
3
4
5
list_use = [1,2,3,4,5,6,7,8,9]
list_new = list(map(lambda x:x*2, list_use))
print(list_new)
# 运行结果:
# [2, 4, 6, 8, 10, 12, 14, 16, 18]
(2) fiter函数:

filter函数的功能是对传入的可迭代对象中的每个元素,都进行函数判断,并返回True或者False,最后将返回 True 的元素组成一个新的可遍历的集合对象,返回其迭代器。

语法格式:filter(function, iterable)

function参数表示传入的函数,可以是内置函数、自定义函数或者 lambda 匿名函数,iterable表示可迭代对象,可以是列表、元组等,允许一到多个。

一般用于筛除可迭代对象的不想要的项。

1
2
3
4
5
list_use = [1,2,3,4,5,6,7,8,9]
list_new = list(filter(lambda x:x%2==0, list_use))
print(list_new)
# 运行结果:
# [2, 4, 6, 8]
(3)redeuce函数:

reduce() 函数通常用来对一个集合做一些累积操作。

语法格式:reduce(function, iterable)

function规定必须传入一个包含 2 个参数的函数;iterable 表示可迭代对象,可以是列表、元组等,允许一到多个。

reduce() 函数在Python 3.x 中已经从内置函数中被移除,在functools模块使用 ,需要导入functools模块。

reduce 函数一般用于总结或者概述数据集。

1
2
3
4
5
6
import functools
list_use = [3,4,5,6,7]
list_new = functools.reduce(lambda x,y:x+y, list_use)
print(list_new)
# 运行结果:
# 25

3. 函数装饰器:

(1)闭包:

是指在函数中嵌套其他函数时引用外部函数变量,即在一个内部函数中,对外部作用域的变量进行引用,内部函数即为闭包。

一般情况下,内部函数是外部函数的返回值。

闭包无法修改外部函数的局部变量。

举例:

1
2
3
4
5
6
7
def add_two(a):
def add_new(b):
return a+b
return add_new
print(add_two(2)(3))
# 运行结果:
# 5
(2)装饰器:

是闭包的一个应用,能够使得代码更简短。

装饰器是用于拓展原函数功能的一种函数,不需要修改原函数的内容和调用。

装饰器常用于授权、日志等行为。

语法格式:

def 装饰器函数名(唯一形参):

函数体

@装饰器函数名

def 被装饰的函数名(形参列表):

函数体

使用时直接调用被装饰的函数名即可。

装饰器函数的形参需要一个函数作为参数传入,同时需要在内部代码块执行该函数,以保证被装饰函数的正确执行。

传参时和带参数时需要装饰器函数嵌套函数,后面进行介绍。

Python内置了3种函数装饰器,分别是@staticmethod、@classmethod 和@property,我们也可以自己定义函数装饰器。

装饰器完成的内容:

  • 将被装饰的函数作为参数传给装饰器函数(后面->前面)。

  • 将被装饰的函数的返回值替换成装饰器函数的返回值(前面->后面)。

实际上,就是把装饰器函数的功能按一定逻辑顺序加入到被装饰的函数当中,使得原函数不需要修改。

因此,不用@函数也可以完成装饰器的功能,只是相对而言阅读比较困难。

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def use_decorator_fun(used_for_decorator_fun):
print("添加新功能的位置,在被装饰的函数执行之前执行")
used_for_decorator_fun()
print("添加新功能的位置,在被装饰的函数执行之后执行")
return True
@use_decorator_fun
def used_for_decorator_fun():
print("执行正常功能中")
for i in range(1,11,2):
print(i,end=',')
print("\n执行完毕")

result = used_for_decorator_fun
if result:
print("执行成功")
# 运行结果:
# 添加新功能的位置,在被装饰的函数执行之前执行
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 添加新功能的位置,在被装饰的函数执行之后执行
# 执行成功

如果不用@,可以是以下形式来表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def use_decorator_fun(used_for_decorator_fun):
print("添加新功能的位置,在被装饰的函数执行之前执行")
used_for_decorator_fun()
print("添加新功能的位置,在被装饰的函数执行之后执行")
return True
def used_for_decorator_fun():
print("执行正常功能中")
for i in range(1,11,2):
print(i,end=',')
print("\n执行完毕")
used_for_decorator_fun =use_decorator_fun(used_for_decorator_fun)
result = used_for_decorator_fun
if result:
print("执行成功")
# 运行结果:
# 添加新功能的位置,在被装饰的函数执行之前执行
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 添加新功能的位置,在被装饰的函数执行之后执行
# 执行成功

可以看到,@use_decorator_fun只是换成了used_for_decorator_fun =use_decorator_fun(used_for_decorator_fun),不过此句的位置换到了两个函数定义之后。

这就是装饰器的实质。

(3)装饰器传参:

被装饰的函数带有参数时,需要对装饰器函数进行处理,以便前者为后者传递参数。

此时,需要为装饰器函数增加一个嵌套函数,嵌套的内部函数带有形参列表,如果其接收参数数量确定可以直接指定好形参列表数量,但多数时候参数数量是不固定的,此时使用前文已讲述的过的两个参数*args和**kwargs来完成接收任意数量参数的要求。

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def fun_use_add(fun_use):
def fun_use_add_fact(a):
print("添加新功能的位置,在被装饰的函数执行之前执行")
fun_use(a)
print("添加新功能的位置,在被装饰的函数执行之后执行")
return True
return fun_use_add_fact
@fun_use_add
def fun_use(a):
print("执行正常功能中")
for i in range(1,a,2):
print(i,end=',')
print("\n执行完毕")
result = fun_use(11)
if result:
print("执行成功")
# 运行结果:
# 添加新功能的位置,在被装饰的函数执行之前执行
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 添加新功能的位置,在被装饰的函数执行之后执行
# 执行成功

此时完成了一个参数的传递,如果参数不固定,可以改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def fun_use_add(fun_use):
def fun_use_add_fact(*args,**kwargs):
print("添加新功能的位置,在被装饰的函数执行之前执行")
fun_use(*args,**kwargs)
print("添加新功能的位置,在被装饰的函数执行之后执行")
return True
return fun_use_add_fact
@fun_use_add
def fun_use(a):
print("执行正常功能中")
for i in range(1,a,2):
print(i,end=',')
print("\n执行完毕")
result = fun_use(11)
if result:
print("执行成功")
# 运行结果:
# 添加新功能的位置,在被装饰的函数执行之前执行
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 添加新功能的位置,在被装饰的函数执行之后执行
# 执行成功
(4)带参数的装饰器:

装饰器除了接收原函数任意类型和数量的参数,还可以接收自己定义的参数。

此时,需要在装饰器函数外部额外嵌套一层函数,该层负责接收自己定义的参数,内部代码块的对应return也要添加。

同时,在@处需要在函数名后增加要传入的实参,注意,此处必须传入对应参数。

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def fun_use_parameter(a,b):
def fun_use_add(fun_use):
def fun_use_add_fact(*args,**kwargs):
print("添加新功能的位置,在被装饰的函数执行之前执行")
for i in range(1,a+1):
print("第"+str(i)+"次执行函数功能,函数功能序号为"+str(b))
fun_use(*args,**kwargs)
print("添加新功能的位置,在被装饰的函数执行之后执行")
return True
return fun_use_add_fact
return fun_use_add
@fun_use_parameter(2,5)
def fun_use(a):
print("执行正常功能中")
for i in range(1,a,2):
print(i,end=',')
print("\n执行完毕")
result = fun_use(11)
if result:
print("执行成功")
# 运行结果:
# 添加新功能的位置,在被装饰的函数执行之前执行
# 第1次执行函数功能,函数功能序号为5
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 第2次执行函数功能,函数功能序号为5
# 执行正常功能中
# 1,3,5,7,9,
# 执行完毕
# 添加新功能的位置,在被装饰的函数执行之后执行
# 执行成功

python进阶——函数(三)
https://github.com/xiaohei07/xiaohei07.github.io/2023/07/12/python进阶——函数(三)/
作者
07xiaohei
发布于
2023年7月12日
许可协议