本章内容
- 高阶函数
- 装饰器
- 闭包
- 递归函数
- 迭代器和生成器
前言
接着上一篇函数进行整理。。
一、高阶函数
高阶函数就是将一个函数以参数的形式传入另一个函数
1 def main_func(func):
2 # 定义一个主函数,并设置一个参数func
3
4 return func
5 # 返回func的值,因为我需要传入一个函数,即返回func的返回值
6
7 def func():
8 # 定义一个函数作为参数传入主函数
9
10 return "Lyon"
11 # 返回 "Lyon" 给func()
12
13 res = main_func(func())
14 # res接收main_func的返回值,将func()的返回值作为参数传入main_func函数
15
16 print(res)
17 # 打印结果 : Lyon
二、装饰器
什么是装饰器?听名字我们就知道是一个进行装饰的工具,装饰什么?当然是装饰函数,即给原来的函数加上一些功能。
装饰器是由函数去生成的,用于装饰某个函数或者方法或者类(类以后再说),他可以让这个函数在执行之前或者执行之后做一些操作。反正就是给函数加功能。
语法:
1. def decorator(func) :
2. return func
3. @decorator @ + "函数名" 是python中的一种语法糖
4. def func() :
5. pass
学习装饰器,首先得知道上述 @ + "函数名" 这个语法糖 到底进行了些什么操作。
看下面这个等式帮助理解:
@decorator = decorator(func) , func = decorator的返回值
就利用上述语法作为例子,来说一下语法糖 进行的操作:
首先 @ + "函数名" ---> 将该操作下面的函数的函数名(即func)作为参数传入装饰器函数(即decorator),等装饰器函数执行完之后又将装饰器函数的返回值返回给函数名。
- 第一个版本
1 def decorate(func):
2 # 定义装饰器函数,func参数接收被装饰函数名
3
4 return func()
5 # 返回function的返回值给decorate
6
7 @decorate #给function函数装上decorate函数
8 def function():
9 # function最后会接收decorate的返回值
10
11 return "装饰成功!"
12 # function的返回值为 "装饰成功!"
13
14 res = function
15 # 进行调用,不要加括号,加了会报错。----> 传递过程在下面
16
17 print(res)
18 # 打印结果 :"装饰成功!"
函数的调用其实就是调用函数名,而函数名其实就是一个内存地址,方式是通过 括号"( )"进行调用。
传递过程:function --> decorate(function) --> function() --> decorate --> function
传递过程注解:函数名 --> decorate中的参数 --> 加括号进行调用 --> 返回decorate --> 返回函数名
通过传递过程我们可以知道,在过程中function已经进行了调用,所以最后我们进行调用的时候是不能在加括号的,因为function此时已经是运行后拿到了返回值。
- 第二个版本
1 def decorate(func):
2 # 定义装饰器函数,func参数接收被装饰函数名
3
4 def inner():
5 # 这一步的作用通过调用方式基本能看出来了
6
7 return func()
8 # 将function的返回值给inner
9
10 return inner
11 # 将inner内存地址返回给decorate
12
13 @decorate #给function函数装上decorate函数
14 def function():
15 # function最后接收的是一个内存地址
16
17 return "装饰成功!"
18 # function的返回值为 "装饰成功!"
19
20 res = function()
21 # 利用 ( ) 调用其函数名,函数名现在对应的是inner的内存地址
22
23 print(res)
24 # 打印结果 :"装饰成功!"
一般我们用的是第二个版本,因为最后调用方式跟我们进行函数调用的方式是一样的。
*语法糖:指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖主要是为程序员提供更实用的编码方式,提高代码的可读性,并有益于更好的编码风格。
通过以上基本已经了解了装饰用的用法,以及原理。
更多示例:

1 def decorator1(func):
2 def inner():
3 return func()
4 return inner
5
6 def decorator2(func):
7 def inner():
8 return func()
9 return inner
10
11 @decorator1
12 @decorator2
13 def function():
14 print("执行函数...")
15 function()

1 def decorator(func):
2 def inner(name):
3 #被装饰函数参数所放位置
4
5 return func(name)
6 return inner
7
8 @decorator
9 def function(name):
10 print("my name is %s" % name)
11
12 function("Lyon")
三、闭包
闭包:必须是内部定义的函数(嵌套函数),该函数包含对外部作用域而不是全局作用域名字的引用。
进一步解释:在嵌套函数中,我们可以将函数作为参数(高阶函数)或者返回值进行传递,函数作为一个容器元素,作为一个变量可以去进行赋值。
闭包的作用:
1. 可以不动原函数里面的代码,并给他新增功能的一个手段。(即装饰器)
1 # 版本一
2 # 直接函数名调用
3 def func():
4 # 定义了一个函数,要给他加功能
5
6 print("我是func")
7 # 执行func内部操作
8
9 return func
10 # 返回None
11
12 def decorator(func):
13 # 功能函数
14
15 print("我是func之前的decorator")
16 # 功能函数中的功能
17
18 func()
19 # 调用传入的 函数名-->指向内存地址 用()进行调用
20
21 return decorator
22 # 返回None
23
24 func = decorator(func)
25 # 将decorator和func的调用操作赋给了 func-->定义的变量名
26
27 func
28 # 功能实现--->加功能实际上是让他先执行我的功能函数然后再执行我的函数
29
30 # 版本二
31 # 改变调用方式
32 def decorator(func):
33 def inner():
34 print("我是func之前的decorator")
35 func()
36 return inner
37 # inner并么有进行调用,所以返回给decorator之后还可以用括号进行调用
38
39 def func():
40 print("我是func")
41 return func
42
43 func = decorator(func)
44 # 覆盖原来的func
45
46 func()
47 # 调用装饰后的函数 --> 即返回的 inner的内存地址
这样我们就可以看出,装饰器其实就是利用闭包原理实现的,只不过利用语法糖来简化了我们的调用方式。

1 def decorator(func): 2 def inner(*args,**kwargs): 3 print("我是func之前的decorator") 4 func(*args,**kwargs) 5 return inner 6 def func(*args,**kwargs): 7 print("我是func") 8 print(args,kwargs) 9 return func 10 func = decorator(func) 11 func( ) --> inner( ) 12 13 加参数版本
2. 需要对某个函数的参数提前赋值
1 def func():
2 name = "Lyon"
3 def inner():
4 print(name)
5 return inner
6 s = func()
7 print(s.__closure__)
8 # __closure__方法可以返回闭包函数中引用变量(即name)的取值,__closure__里包含了一个元组(tuple),这个元组中的每个元素是cell类型的对象。
9
10 """
11 例子中我们进行调用inner时需要用到name变量。如果我们将name变量定义在inner中,当inner进行调用时,python会先将name存到内存中,等inner执行结束后,python又会把name给清空,那如果我们调用一万次inner,python解释器就要创建一万次再清空一万次,这样的调用过程会浪费很多内存,而闭包函数,他会先将要用的变量创建好,等以后都不用了再将他从内存中清空。
12 所以闭包还可以对所需要用到的参数进行提前赋值,减少内存消耗。
13 """

1 s = [lambda x: x + i for i in range(10)]
2 print(s[0](10))
3 print(s[1](10))
4 print(s[2](10))
5 print(s[3](10))
6
7 """
8 请看完匿名函数后再来怼怼这个问题
9
10 """
11 # 翻译版本
12 def func():
13 l = []
14 for i in range(10):
15 def inner(x):
16 return i + x
17 l.append(inner)
18 print(inner)
19 return l
20 res = func()
21 print(res[0](10))
22 print(res[1](10))
23 print(res[2](10))
24 print(res[3](10))
四、递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自己本身,这个函数就是递归函数。既然是调用自身那每次调用,需要解决的问题就应该有所减少,不然这个函数就没有尽头的执行下去。
1 def counter(num): 2 # 定义一个函数counter 3 4 print(num) 5 # 打印num 6 7 if num <= 0: 8 # 如果num小于等于0 9 10 return num 11 # 返回num 12 13 num -= 1 14 # 必须相对上一次有所减少 15 16 counter(num) 17 #反复调用,直到return将函数停止运行 18 19 counter(10) 20 # 调用函数
用递归实现斐波那契数列
1 def counter(n1,n2): 2 if n1 > 1000: 3 return "不搞了!" 4 print(n1) 5 n3 = n1 + n2 6 counter(n2,n3) 7 counter(0,1)
更多资料 --> 安生,大好时光。