第六章 6 函数-迭代器与生成器 练习题标签:练习题,迭代,生成器,add,range,print,表达式 From: https://www.cnblogs.com/leeyong49/p/16666867.html
[基础知识]
1 说说 python 中装饰器、迭代器的用法;描述下 dict 的 items()方
法与 iteritems()方法的不同;
解答:
装饰器:
装饰器是指对函数的执行过程 ,做一些扩展,甚至可以更改本身函数的执行 。
迭代器:
迭代器是指遵循迭代器协议的对象,这类对象在被for循环时,每次迭代生成一下个项,
不用一开始就生成整个列表。
dict下的items()方法,返回的就是可迭代对象。
2 下列数据结构中,哪一种是不可迭代的
A. dict
B. object
C. set
D. str
B////字典,字符串,集合,都是可以迭代的
对象是不能迭代的
3 使用列表推导式生成包含 10 个数字 5 的列表,语句可以写为
alist = [5 for i in range[10]
4 关键字__________用于测试一个对象是否是一个可迭代对象的元素
in
5 使用列表推导式得到 100 以内所有能被 13 整除的数的代码可以写
作___________________________________
alist = [i for i in range(100) if i%13 == 0]
print(alist) # [0, 13, 26, 39, 52, 65, 78, 91]
6 表 达 式 [x for x in [1,2,3,4,5] if x<3] 的 值 为
_____________________
[1,2]
7 表达式 [index for index, value in enumerate([3,5,7,3,7]) if value
== max([3,5,7,3,7])] 的值为__________________
[2,4]
我的理解,这是一个列表推导式:
[{index} for {index, value} in {enumerate([3,5,7,3,7])} if {value ==max([3,5,7,3,7])}
我刚刚被迷惑,猛一看还没看明白 ,百度才知道是这个理解。原来是个列表生成式。
其实就是选出enumerate枚举的下标值,这个枚举没有指定下标start开始值,以0默认
所以,值为2,4
8 已知x = [4,5,3,7] ,那么表达式 [x.index(i) for i in x if i==3] 的
值为______________
[2]
9 已知 vec = [[1,2], [3,4]],则表达式 [col for row in vec for col in
row] 的值为_____________________
[1,2,3,4]
10 已知 vec = [[1,2], [3,4]],则表达式 [[row[i] for row in vec] for
i in range(len(vec[0]))] 的值为_________________________
[[1,3],[2,4]]
11 表达式 len([i for i in range(10)]) 的值为__________
10
12 表达式 [str(i) for i in range(3)] 的值为____________
['0', '1', '2']
13 表达式 [i for i in range(10) if i>8] 的值为________________
[9]
14 已知有列表 x = [[1, 2, 3], [4, 5, 6]],那么表达式 [[row[i] for row
in x] for i in range(len(x[0]))] 的 值 为
___________________________
[[1, 4], [2, 5], [3, 6]]
15 已知 x = range(1,4) 和 y = range(4,7),那么表达式 sum([i*j
for i,j in zip(x,y)]) 的值为__________
x = range(1,4)
y = range(4,7)
print(sum([i * j for i, j in zip(x, y)])) # 32
print(list(x)) # [1, 2, 3]
print(list(y)) # [4, 5, 6]
print(list(zip(x, y))) # [(1, 4), (2, 5), (3, 6)]
16 表达式 [5 for i in range(3)] 的值为_______________
[5,5,5]
17 已知 x = [[1, 2, 3,], [4, 5, 6]],那么表达式 sum([i * j for i, j in
zip(x[0],x[1])]) 的值为______
x = [[1, 2, 3,], [4, 5, 6]]
print(sum([i * j for i, j in zip(x[0], x[1])])) # 32
18 已知列表 x = [1, 2, 3] 和 y = [4, 5, 6],那么表达式 [(i,j) for i, j
in zip(x,y) if i==3] 的值为____________
x = [1, 2, 3]
y = [4, 5, 6]
print([(i, j) for i, j in zip(x, y) if i == 3]) # [(3, 6)]
19 已知 x = [3, 2, 3, 3, 4],那么表达式 [index for index, value in
enumerate(x) if value==3] 的值为____________
x = [3, 2, 3, 3, 4]
print([index for index, value in enumerate(x) if value == 3]) # [0, 2, 3]
20 表达式 5 if 5>6 else (6 if 3>2 else 5) 的值为_________
6
21 写一个列表生成式,产生一个公差为 11 的等差数列
alist = [i for i in range(1,100,11)]
print(alist) # [1, 12, 23, 34, 45, 56, 67, 78, 89]
22 字典推导式?
dict = {key:value for (key,value) in iterable}
23 列表推导式和生成器表达式 [i % 2 for i in range(10)] 和 (i % 2
for i inrange(10)) 输出结果分别是什么?
[0,1,0,1,0,1,0,1,0,1]
<generator object <genexpr> at 0x000002D2324F6340>
24 简述 yield 和 yield from 关键字。
yield:
当一个函数中出现yield关键字的时候,那么这个函数就是一个生成器。可以用for循环或者
next()函数来迭代。
yield from:
简单的说,yield from generator。实际上就是返回另外一个生成器。
[进阶拓展]
1 使用生成器编写 fib 函数, 函数声明为 fib(max), 输入一个参数
max 值, 使得 该函数可以这样调用。
for i in range(0,100):
print fib(1000)
# 并产生如下结果(斐波那契数列),1,1,2,3,5,8,13,21...
def fib(max):
x, y = 0, 1
while True:
j = x+y
yield j
y = x
x = j
if x > max:
break
for i in range(0,100):
print(list(fib(1000)))
2 python 一行 print 出 1~100 偶数的列表, (列表推导式, filter 均
可)
print([i for i in range(1,100) if i%2==0])
print(list(filter(lambda x :x%2==0,range(1,100))))
3 以下代码输出是什么,请给出答案并解释
def multipliers():
return [lambda x:x*i for i in range(4)]
print([m(2) for m in multipliers()])
...这个题目的答案我都没看明白。。。。
4 下面这段代码的输出结果将是什么?请解释。
def multipliers():
return [lambda x : i * x for i in range(4)]
print [m(2) for m in multipliers()]
抄答案,,,答案也看不懂
上面代码的输出结果是【6,6,6,6】 不是想的【0,2,4,6】
上述问题产生的根本原因是python闭包的延迟绑定。这意味着内部函数在被调用时,
参数的值在闭包内进行查找。因此,当任何由multipliers()返回的函数被调用时,i的值将
在附近的范围内进行查找。那时,不管返回的函数是否被调用,for循环已经完成,不被赋予
了最终的值3。因此,每次返回的函数乘以传递过来的值3,因为上段代码传递过来的值是2,它们
最终返回的值都是6。下面是解决这一问题的一些方法。一种方法就是用python生成器。
def multipliers():
for i in range(4):yield lambda x:i*x
# 另外一个解决方案就是创造 一个闭包,利用默认函数立即绑定
def multipliers():
return [lambda x ,i=i: i*x for i in range(4)]
[面试真题]
1 现有 [[1, 2], [3, 4], [5, 6]] 使用一行代码展开该列表,
得出[1, 2, 3, 4, 5, 6]
alist = [[1, 2], [3, 4], [5, 6]]
alist = [a for i in alist for a in i ]
print(alist) # [1, 2, 3, 4, 5, 6]
2 阅读下面代码,推导最后结果,并列出推导过程。
def add(l, i):
return l + i
def test():
for i in range(3):
yield i
g = test()
for n in [1, 5, 10]:
g = (add(n, i) for i in g)
print(list(g))
【参考答案】
大前提:生成器对象有一个巨大的坑——惰性计算。
函数自上而下执行,一直到 print(list(g)) 生成器表达式才开始执行,将 11 - 12 行
拆开来看:
n = 1
g = (add(n, i) in g)
n = 5
g = (add(n, i) for i in g)
n = 10
g = (add(n, i) for i in g)
将其合并,其中 n = 10
g = (add(n, i) for i in (add(n, i) for i in (add(n, i) for i in test())))
从里面往外执行,
test() —> (0, 1, 2)
(add(n, i) for i in test()) –> (10, 11, 12)
(add(n, i) for i in (add(n, i) for i in test()) —> (add(n, i) for i in (10, 11, 12)) —> (20, 21, 22)
(add(n, i) for i in (add(n, i) for i in (add(n, i) for i in test()))) —> (30, 31, 32)
g = (30, 31, 32)
list(g) = [30, 31, 32]
因此最后的结果是:[30, 31, 32]
3 生成器比迭代器更好的地方是什么?
生成器能做到迭代器能做的所有事,而且因为自动创建了 iter()和 next()方法,生成器显得特
别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了
创建和保存程序状态的自动方法,当生成器器终结时,还会自动抛出 StopIteration 异常