1. 高阶函数
1.1 map/reduce
(1)map 函数
map(function_to_apply, list_of_inputs)
- function_to_apply 代表函数
- list_of_inputs 代表输入序列
- 返回迭代器
# 如要实现列表中每个元素的平方,并返回新列表
items = [1, 2, 3, 4, 5]
squared = []
for i in items:
squared.append(i**2)
# 用map实现
items = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, items))
(2)reduce 函数
reduce(function, iterable[, initializer])
- function 表示函数
- iterable 表示序列
- initializer 初始值(可选)
def add(x, y ):
return x + y
result = reduce(add, [1,2,3,4,5])
print(result)
1.2 filter
用于过滤序列 filter(function, iterable)
- function 判断函数
- iterable 可迭代的对象
- 返回的是一个 iterator ,是一个惰性序列。要强迫 filter() 完成计算结果,需要用list()函数获得所有结果并返回 list
# 埃氏筛法
# 定义筛选函数,判断输入是否能被n整除,如果被整除那么这个输入就不是素数
def _not_divisible(n):
return lambda x: x % n > 0
# 定义一个生成器,不断返回下一下素数
def primes():
yield 2 # 输出一个素数
it = _odd_iter()
while True:
n = next(it) # 返回序列的第一个数
yield n
it = filter(_not_divisible(n), it)
# 打印1000以内的素数:
for n in primes():
if n < 1000:
print(n)
else:
break
1.3 sorted
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print(sorted(students, key=lambda s:s[2], reverse=True))
2. 返回函数
# 返回求和函数的函数
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f = lazy_sum(1,2,3,4,5)
print(f)
print(f())
>>> <function lazy_sum.<locals>.sum at 0x000001C14A986620>
>>> 15
- 在函数 lazy_sum 中又定义了函数 sum,并且,内部函数 sum 可以引用外部函数 lazy_sum 的参数和局部变量
- 当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)
- 调用 lazy_sum() 时,返回的并不是求和结果,而是求和函数。注意:调用 lazy_sum() 时,即便每次传入相同参数,但最终返回的函数还是不同的
- 调用函数 f 时,才真正计算求和的结果
注意!返回闭包时要牢记:返回函数不要引用任何循环变量,或者后续会发生变化的变量。如下例:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print(f1())
>>> 9
print(f2())
>>> 9
print(f3())
>>> 9
答案全部都是9,而不是1 4 9 的原因是,返回的函数引用了变量 i ,但是并非立刻执行。等到3个函数都返回,它们引用的变量 i 均为3,因此最后是9
-
原因在于,对于闭包来说,外函数会认为自己的临时变量可能在将来的内部函数中用到,所以每次外部函数结束时,它都在返回内部函数的同时,把自己(外部函数)的临时变量和内部函数绑定在一起,这就解释了全部都是9的原因。
-
如果一定要引用循环变量,我们可以把每次循环的值,绑定给一个内层的函数。这样一来,无论该循环变量后续如何更改,已绑定到函数参数的值都不会变化了。
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()
运行步骤:
- 进入【count()】,因为还没调用 所以不进入内函数,进入【for循环】,i = 1,进入【f(1)】,进入【g()】,最后f() 返回一个绑定的参数 j=1和函数g(),函数添加到 fs=[ ] 中
- 接着再进入【count()】,i = 2,进入【f(2)】,进入【g()】,最后f() 返回一个绑定的参数 j=2和函数g(),函数添加到 fs=[ ] 中
- 同理得到循环 i = 3
- 这样,最后 f1, f2, f3 = count(),就得到三个不同的值了