一、返回函数
函数作为 "返回值" 返回。特点是返回函数在调用的时候才运行计算。
# 实例1,求传入值的平方
def func(n):
def func1():
return n*n
return func1
print(func(2))
>>> <function func.<locals>.func1 at 0x00000000024CFA60>
在这个实例中,我们定义了两个函数,func1 返回的是一个平方值,而 func 返回的是 func1 这个函数本身。当我们调用 func 这个函数的时候,返回的是函数 func1,但是并没有计算出结果。
# 实例2,接上面的例子
#我们把func(2)赋值给变量 a,并且运行 a()
a=func(2)
print(a())
>>> 4
# 所以,只有运行 函数 a() 的时候,才会返回运算结果
我们来看一个返回函数的例子
# 实例3,返回1,2,3 的2倍的值
def func1():
ls=[]
for i in range(1,4):
def func2():
return i*2
ls.append(func2)
return ls
a1,a2,a3=func1()
print(a1())
print(a2())
print(a3())
>>> 6
6
6
# a1,a2,a3=func1(),这个是给这三个变量依次赋值,值为函数
# 按照我们的想法,这三个值应给为 2,4,6,为什么结果成了6,6,6 了?这里我们引入一个新的知识,这就是闭包。我们先不说解释什么是闭包,我们先来分析一下该函数的执行的顺序以及过程。
# 实例3分析
def func1():
# 首先定义 func1 这个函数
ls=[]
# 接着定义 空的列表ls
for i in range(1,4):
# for循环,并分次把 1,2,3 赋值给变量 i
for i in range(1,4):
def func2():
return i*2
ls.append(func2)
return ls
# 红色的部分为 for 循环的内部语句,for 循环的次数为3次。首先 for 每次循环都要创建新的函数 func2,函数的返回值为 变量 i * 2。函数创建完毕后,接着运行 ls.append(func2),添加的值为函数,并不是直接添加计算结果。for 循环完毕后,返回列表 ls。最后把函数 func1 的返回值分别赋值给 a1,a2,a3。
# 以上是程序的运行过程,我们接着来说内部的运行逻辑。当然,主要是红色部分的代码。
for i in range(1,4):
def func2():
return i*2
ls.append(func2)
# 首先,for 循环生成了 i=1 的变量,开始第一次循环,创建一个新的函数func2,接着运行ls.append(func2),向列表 ls 添加一个元素,这个元素是一个函数 fun2,但是函数并没有运行起来,而是相当于 "挂" 起来了,就此第一次循环完毕。
# 接着第二次循环,i=2,创建一个新的函数 func2,接着想 ls 添加函数 func2,和第一次一样,函数并没有运行,第二次循环完毕。
# 第三次循环 i =3,创建一个新的函数 func2,接着想 ls 添加函数 func2,和第一次一样,函数并没有运行,第三次循环完毕。
# 这时候,for 循环完,i 的值为3。接着返回列表 ls 。这时,函数 func1 也已经定义完。
# 运行 a1,a2,a3=func1(),把列表 ls 中的三个函数分别赋值给a1,a2,a3
# 接着运行 print(a1()) print(a2()) print(a3()),这时候的a1,a2,a3已经是代表的三个对应的函数。此时,函数 func2才真正的运行起来了,可 i 的值已经为3了。所以三个函数的输出值都为 6 。
# 函数的返回值为函数,且内部函数调用外部变量和参数的情况,称为闭包。(我是这么理解的==!见笑了),如果破解这种情况呢?我们看实例4
# 实例4,破解闭包
def func1():
ls=[]
for i in range(1,4):
def func2(j):
def func3():
return j*2
return func3
ls.append(func2(i))
return ls
a1,a2,a3=func1()
print(a1())
print(a2())
print(a3())
>>> 2
4
6
# 只需要再新建一个函数,把 for 循环的变量 i 的值,传入新函数的参数中,然后就可以放心的调用参数了。
二、匿名函数
使用 lambda 创建一个匿名函数。语法如下
lambda 参数1、参数2......:语句
- 匿名函数没有对应的函数变量,但可以自己指定变量
- 匿名函数只能有一个表达式
- 可以没有参数,参数也可以是可变参数、关键字参数和命名关键字
# 实例5
print(list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
>>> [1, 4, 9, 16, 25, 36, 49, 64, 81]
# 可以利用 map 函数来构建list,方便快捷
# 实例6,两个参数,表达式为判断语句
a =lambda x,y:True if x>y else False
print(a(2,3))
>>> False
# 把匿名函数赋值给变量 a,在使用 a 往匿名函数带入参数
# 实例7,lambda 的可变参数
b=lambda *args:list(args)
print(b(1,2,3))
>>> [1, 2, 3]
# 事实证明,lambda 的参数也可以是可变参数
# 实例8,lambda 的关键字参数
c=lambda **kw:True if kw['name']=='zhangsan' else False
print(c(name='zhangsan',age=18))
>>> True
# 在一次证明,关键字参数也是可以的
# 实例9,lambda 的命名关键字参数
d=lambda name,age,*,job :'My name is '+name+', i am '+str(age)+", "+'job is '+job
print(d('zhangsan',18,job='Study'))
>>> My name is zhangsan, i am 18, job is Study
# 成功带入命名关键字参数
# 综上实例,我们可以看到,就参数而言,和正常函数是没有什么区别的。但是执行语句lambda只能有一个表达式,而正常函数是可以有很多的。
关注公众号,了解更多!