返回函数
1,实例1:可变参数求和
(1)即时返回求和结果
def calc_sum(*args):
ax = 0
for n in args:
ax = ax + n
return ax
(2)返回求和函数,调用该函数则得结果
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
#调用lazy_sum()函数
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>
#调用f()函数,得求和结果
>>> f()
25
- 在函数
lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种程序称为“闭包(Closure)” - 调用
lazy_sum()
时,每次调用都会返回一个新的函数,即使传入相同的参数,结果函数也不相同
>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False
>>> f1()
25
>>> f2()
25
2,实例2(闭包):依次返回1,2,3的平方数值
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs
#结果
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9
3,实例3(nonlocal):返回递增整数的计数器函数
(1)如果只是读外层变量的值,返回的闭包函数调用一切正常:
def inc():
x = 0
def fn():
# 仅读取x的值:
return x + 1
return fn
f = inc()
print(f()) # 1
print(f()) # 1
(2)如果对外层变量赋值,由于Python解释器会把x当作函数fn()的局部变量,它会报错:
def inc():
x = 0
def fn():
# nonlocal x
x = x + 1
return x
return fn
f = inc()
print(f()) # 1
print(f()) # 2
原因是x
作为局部变量并没有初始化,直接计算x+1
是不行的。但我们其实是想引用inc()
函数内部的x
,所以需要在fn()
函数内部加一个nonlocal x
的声明。加上这个声明后,解释器把fn()
的x
看作外层函数的局部变量,它已经被初始化了,可以正确计算x+1
。
- 使用闭包时,对外层变量赋值前,需要先使用
nonlocal
声明该变量不是当前函数的局部变量。
(3)练习:利用闭包返回一个计数器函数,每次调用它返回递增整数:
# -*- coding: utf-8 -*-
def inc():
x = 0
def fn():
nonlocal x
x = x + 1
return x
return fn
# 测试:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
print('测试通过!')
else:
print('测试失败!')
匿名函数
1,匿名函数:lambda
表示
- 关键字
lambda
表示匿名函数,冒号前面的x
表示函数参数 - 匿名函数有个限制,就是只能有一个表达式,不用写
return
,返回值就是该表达式的结果 - 匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
- 可以把匿名函数作为返回值返回
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
def build(x, y):
return lambda: x * x + y * y
2,练习
问:请用匿名函数改造下面的代码:
# -*- coding: utf-8 -*-
def is_odd(n):
return n % 2 == 1
L = list(filter(is_odd, range(1, 20)))
#改造后
L = list(filter(lambda n: n%2 == 1, range(1, 20)))
print(L)