我们知道理论上使用循环方式构建列表都可以通过生成器替代
以生成斐波那契数列为例
def fib(max):
n, a, b = 0, 0, 1
fib_list = []
while n < max:
fib_list.append(b)
a, b = b, a + b
n = n + 1
return fib_list
fib(10)
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
list(fib(10))
但递归中要怎么用生成器呢?
以获取接口所有分页数据为例
递归+生成器:
def get_all_itmes():
url = 'https://reqres.in/api/users'
# 递归取下一页数据
def get_next_page(pindex):
# 获取数据
# 生成params
params = {
'page':pindex
}
# 发送请求
result = requests.get(url, params=params, verify=True)
result_json = result.json()
if result_json['data'] != []:
for item in result_json['data']:
yield item
yield from get_next_page(pindex+1)
# 启动
return list(get_next_page(1))
%timeit get_all_items()
2.1 s ± 521 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3.27 s ± 1.16 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
1.88 s ± 11.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
单纯递归:
def get_all_itmes():
url = 'https://reqres.in/api/users'
data_list = []
# 递归取下一页数据
def get_next_page(pindex):
# 获取数据
# 生成params
params = {
'page':pindex
}
# 发送请求
result = requests.get(url, params=params, verify=True)
result_json = result.json()
if result_json['data'] != []:
for item in result_json['data']:
data_list.append(item)
get_next_page(pindex+1)
get_next_page(1)
return data_list
%timeit get_all_items()
2.96 s ± 201 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3.08 s ± 374 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3.02 s ± 598 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
总结:生成器由于没有使用列表来存储数据,故理论上更快且更节省内存,但此处由于网络IO时间占比更大,所以速度提升不明显,但为了显得代码更高级,更推荐使用递归和生成器的组合。