模块课程(3/4)
生成器表达式
生成器表达式类似于列表理解,但带有 圆括号而不是方括号。差异是巨大的: 它不会在内存中构建列表,它会按需生成元素, 一次一个。
gen = (n * n for n in range(1_000_000))
# istantaneo, memoria costante: nessun calcolo ancora fatto
list_comp = [n * n for n in range(1_000_000)]
# alloca 1M di int in memoria惰性(惰性评估)
在有人请求下一个值之前,生成器不会执行任何操作:
gen = (n * n for n in range(5))
next(gen) # 0 (calcolato adesso)
next(gen) # 1
next(gen) # 4
# ... e così via, fino a StopIteration它会耗尽:消耗完所有元素后,它永远为空。 要重用它,您必须重新创建它。
何时使用它
当您将结果传递给按顺序使用它们的函数时:
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costantesum、any、all、max、min、"".join(...) 都接受生成器。
如果外部函数只需要调用括号,则可以
省略生成器自己的:
sum((n * n for n in range(10))) # OK
sum(n * n for n in range(10)) # IDENTICO, più leggibileany 和 all:短路
any(...) 和 all(...) 一旦得到答案就停止迭代。
使用生成器,甚至不会计算以下元素。
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums) # True (si ferma a 4)
all(n > 0 for n in nums) # True
all(n > 2 for n in nums) # False (si ferma a 1)模式:惰性管道
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
prime_dieci.append(r)
if len(prime_dieci) == 10:
break即使投入巨大,也没有中间列表。
使用 sum、any、all 来消耗生成器
生成器表达式非常适合直接传递给使用可迭代对象的函数,例如 sum()、any() 或 all()。在这种情况下,您可以省略生成器表达式的外括号,只需编写:
squares_sum = sum(x**2 for x in range(10))这可以使您的代码保持干净并且具有很高的内存效率。
尝试一下
使用 sum() 中的生成器表达式计算 1 到 100(含)之间的数字的平方和。将其分配给“tot”。评估“总”。
显示提示
range(1, 101) 包括 100。
3 次尝试后可用的解决方案
复习练习
给定 `words = ['ciao', 'mondo', 'PYTHON', 'java']`,使用带有生成器表达式的 any() 来检查是否至少有一个单词是大写 (.isupper())。将结果分配给“has_uppercase”。评估“has_uppercase”。
显示提示
任何(p.isupper()对于单词中的p)
3 次尝试后可用的解决方案
额外的挑战
Use a generator expression passed directly to the `sum()` function to calculate the sum of the squares of all integers from 1 to 100 inclusive. Store the result in `total_sum` and evaluate it.
显示提示
编写total_sum = sum(x**2 for x in range(1, 101))。不需要双括号。
3 次尝试后可用的解决方案