面试题:迭代器和生成器
干咱们这行的,免不了和“迭代器”“生成器”这些词打交道,尤其 Python 里,这俩可是面试高频。
今天咱就从一个经典面试题聊开,说说这俩到底是啥,顺便还帮大家总结一下,遇到相关问题怎么优雅应对,不翻车。
列表推导式 vs 生成器表达式
先抛个问题——有同学在面试被问懵了:
问:将 [] 换成 (),数据结构变了吗?
咱看看这个例子:
L = [x*x for x in range(10)]
print(L)
这不就是个普通列表嘛,输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81],再正常不过。
但是你把方括号换成圆括号:
g = (x*x for x in range(10))
print(g)
这输出可不是列表了,而是:
<generator object <genexpr> at 0x...>
看到 generator 这词没?这玩意儿就叫生成器表达式,确实数据结构变了。列表推导式直接给你一整个列表,生成器表达式只给你一个生成器对象,它不会一次性算完所有的值,而是要啥算啥,按需生成。
面试回答思路:
“是的,数据结构变了。用 [] 是列表推导式,生成一个完整的列表,占用实际内存;用 () 是生成器表达式,返回一个生成器对象,按需计算,节省内存。”
为啥有生成器?为啥不用列表?
你想象一下,老板让你处理一份包含一百万条数据的文件,用列表推导式直接全加载,内存炸不炸咱不知道,反正电脑风扇得起飞。
生成器就不一样了,边循环边计算,你要一个,我给一个,别催。这就叫“惰性计算”,省内存不说,还特别适合处理大数据流,比如读取日志文件、爬虫抓取数据等等。
来个小对比:
# 列表:一口气全算出来
L = [x*x for x in range(1000000)]
# 生成器:需要的时候才算
g = (x*x for x in range(1000000))
这俩的内存占用,那叫一个天壤之别,生成器轻飘飘,列表沉甸甸。
生成器的真面目:yield 出场
说到生成器,不提 yield 说不过去。这可是 Python 里一等一的神器。
平时写函数,咱都用 return,一次性扔回去一个值,函数结束。而 yield 就不一样了,它让函数变成一个生成器,每次暂停在 yield,下次从这儿接着来,状态还能保留。
看例子:
defmy_gen():
for i in range(3):
yield i
g = my_gen()
print(next(g)) # 0
print(next(g)) # 1
print(next(g)) # 2
每次 next(g),生成器往前走一步,到了 yield 交个值,暂停。再 next,从上次停的地方接着走,直到抛出 StopIteration,这才算走完。
这种按需产出、状态保存的操作,别说写爬虫,处理大数据、流式传输、协程啥的,简直就是救命稻草。
迭代器和生成器的区别到底在哪儿?
面试官一问,你别慌,咱得分得清:
迭代器(Iterator):只要实现了
__iter__()和__next__()这俩方法的对象,都叫迭代器。它知道自己到哪了,每次next()都能拿到下一个元素,取完就抛StopIteration。生成器(Generator):生成器本质就是一种特殊的迭代器,自动帮你写好了
__iter__()和__next__(),你只需要用yield定义它。
换句话说,生成器是迭代器的一种,但写法简单多了,不用自己手动搞那些魔法方法。
再来个例子感受下迭代器的“原生”写法:
classMyIterator:
def__init__(self):
self.n = 0
def__iter__(self):
return self
def__next__(self):
if self.n < 3:
val = self.n
self.n += 1
return val
else:
raise StopIteration
it = MyIterator()
print(next(it)) # 0
print(next(it)) # 1
print(next(it)) # 2
和刚才 yield 写法比,是不是麻烦多了?但效果其实差不多。这也说明了,生成器就是懒人版的迭代器,Python 贴心给我们省事儿。
面试题的最佳回答
问题:将 [] 换成 (),数据结构变了吗?
最佳回答:
“变了,方括号生成的是列表,直接把所有元素存在内存里;圆括号生成的是生成器对象,按需生成元素,只有在迭代时才计算,节省内存。这种生成器表达式特别适合处理大数据或者数据流,避免一次性加载所有数据。”
也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。
对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。