面试题答案
一键面试生成器的创建
在Python中,生成器有两种创建方式:生成器函数和生成器表达式。
生成器函数:
生成器函数是包含 yield
语句的函数。当函数被调用时,它返回一个生成器对象,但并不立即执行函数体。
def my_generator():
for i in range(5):
yield i
生成器表达式: 类似于列表推导式,但使用圆括号而不是方括号。
gen_expression = (i for i in range(5))
迭代过程
生成器对象遵循迭代器协议,这意味着可以在 for
循环中使用它,或者通过 next()
函数逐个获取值。
使用 for 循环迭代:
def my_generator():
for i in range(5):
yield i
for num in my_generator():
print(num)
在这个例子中,for
循环每次请求一个新值时,生成器函数会从上次 yield
暂停的地方继续执行,直到再次遇到 yield
或者函数结束。
使用 next() 函数迭代:
gen = my_generator()
print(next(gen)) # 输出 0
print(next(gen)) # 输出 1
print(next(gen)) # 输出 2
print(next(gen)) # 输出 3
print(next(gen)) # 输出 4
# print(next(gen)) # 这会引发 StopIteration 异常
每次调用 next(gen)
时,生成器生成下一个值并暂停。当没有更多值可生成时,会引发 StopIteration
异常。
节省内存和提高效率
- 节省内存: 生成器并不会一次性生成所有的值并存储在内存中,而是按需生成。相比列表,当需要处理大量数据时,生成器可以显著节省内存。例如,如果要生成从 1 到 1000000 的整数,如果使用列表,会占用大量内存:
large_list = list(range(1000000))
而使用生成器:
large_generator = (i for i in range(1000000))
此时,生成器只在需要时生成值,内存中只存储当前生成的值,而不是所有的值。
- 提高效率: 在某些情况下,生成器可以提高效率。例如,当只需要处理数据流中的前几个值时,生成器不需要生成所有值,从而节省计算资源。比如在一个生成大量随机数并处理前几个的场景:
import random
def random_number_generator():
while True:
yield random.randint(1, 100)
gen = random_number_generator()
for _ in range(5):
print(next(gen))
这个生成器会不断生成随机数,但我们只处理前 5 个,避免了不必要的计算。
综上所述,Python生成器通过按需生成值的机制,与循环机制紧密协同工作,在处理大量数据或只需要部分数据的场景下,能够有效节省内存并提高效率。