生成器
生成器(generator)相比列表推导式,只占用很小的空间,因为它是一边循环一边推算,通过next()
调用下一元素,并在结束时抛出StopIteration
异常,在语法上只要把[]
换成()
即可。
a = (i * i for i in range(10))
print(a) # 生成器对象,不能直接输出
# 用"next(生成器)"或者"生成器.__next__()"来返回下一个元素
print(a.__next__()) # 0
print(next(a)) # 1
for x in a: # for本身也是在一个一个调用next()
print(x, end=' ') # 输出剩下的4 9 16 25 36 49 64 81
可以在函数内使用yield
关键字将该函数变成一个generator,每次调用next()
时执行,执行到yield
时候暂停下来并返回yield
后跟的值,下次调用next()
时继续从刚刚暂停的yield
语句的下一句继续执行。
当某个next()
调用没有遇到yield
就已经结束了整个函数时,就会抛出StopIteration
异常,而不需要raise StopIteration()
。
迭代器
可以依次访问元素(即可以用for
循环遍历)的是可迭代对象(Iterable
);可以用next()
依次访问的可迭代对象是迭代器(Iterator
)。
生成器一定是迭代器,list
、dict
、str
是可迭代对象,但不是迭代器,可以iter()
函数转成迭代器。
from collections import Iterable, Iterator
a = [i for i in range(5)] # 这是一个list
print(isinstance(a, Iterable)) # True,即可迭代
print(isinstance(a, Iterator)) # False,即不是迭代器
b = iter(a) # 转换为迭代器
print(b.__next__()) # 0
print(b.__next__()) # 1
for n in b:
print(n, end=' ') # 2 3 4
高阶函数
函数可以传给变量,也可以像普通变量一样当做参数传给函数,接受函数为参数的函数就是高阶函数。
map()
高阶函数map()
接收一个函数,再接受一个Iterable
,将函数作用在Iterable
中的每个元素上,将返回值组成一个惰性Iterator
序列并返回。
def fun(n):
return n / 2
a = [i * i for i in range(5)] # 可迭代对象(Iterable)
b = map(fun, a) # 返回一个迭代器(Iterator)
print(list(b)) # [0.0, 0.5, 2.0, 4.5, 8.0]
reduce()
高阶函数reduce()
接收一个函数,再接受一个Iterable
,将函数作用在Iterable
中的前两个元素上,将返回值与下一个元素一起再扔给该函数,如此反复。
from functools import reduce
# 传给reduce的函数要接收两个参数
def fun(m, n):
return m + n
a = [i * i for i in range(5)] # 可迭代对象(Iterable)
b = reduce(fun, a) # 反复进行两两计算,最终返回计算结果
print(b) # 30
filter()
高阶函数filter()
的输入输出形式和map()
一样,不过filter()
是将传入的函数作用到Iterable
的每个元素上,最终只保留返回True
的那些元素。也就是过滤掉一些元素,返回原Iterable
的一个带序子集。
from collections import Iterable, Iterator
def fun(n):
if n < 2:
return False
if n < 4:
return True
i = 2
while i * i <= n:
if 0 == n % i:
return False
i += 1
return True
a = range(50) # Iterable
# print(isinstance(a, Iterator)) # False
b = filter(fun, a) # 返回过滤后的Iterator
# print(isinstance(b, Iterator)) # True
print(list(b)) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
sorted()
Java或者C++的排序可以指定一个比较器或者自定义比较大小的函数,在Python里只是指定其key
参数为某个函数,这个函数对排序的元素做一定的变换,使元素按照变换后的值来进行排序,但并未指定比较规则。
a = [3, -2, 8, -6, 0, 4, -9]
b = sorted(a, key=abs, reverse=True) # 按绝对值从大到小排序
print(b) # [-9, 8, -6, 4, 3, -2, 0]