generator'对象不可下标"错误
我在解决Project Euler第11题时,为什么在代码的第5行会出现这个错误呢?
for x in matrix:
p = 0
for y in x:
if p < 17:
currentProduct = int(y) * int(x[p + 1]) * int(x[p + 2]) * int(x[p + 3])
if currentProduct > highestProduct:
print(currentProduct)
highestProduct = currentProduct
else:
break
p += 1
'generator' object is not subscriptable
2 个回答
3
作为对Jeremy回答的补充,这里有一些关于你代码设计的想法:
看你的算法,其实你并不需要真正随机地访问生成器产生的值:在任何时候,你只需要保持四个连续的值(实际上只需要三个,加上一点优化)。这在你的代码中有点模糊,因为你把索引和迭代混在一起了:如果索引能正常工作(但实际上不能),你的y
可以写成x[p + 0]
。
对于这样的算法,你可以使用一种“滑动窗口”的技巧,下面是你代码的简化版示例:
import itertools, functools, operator
vs = [int(v) for v in itertools.islice(x, 3)]
for v in x:
vs.append(int(v))
currentProduct = functools.reduce(operator.mul, vs, 1)
print(currentProduct)
vs = vs[1:]
113
你的 x
值是一个生成器对象,这是一种 Iterator
:它会按照请求的顺序生成值,通常是通过 for
循环或者调用 next(x)
来获取。
你现在试图像访问列表或其他 Sequence
类型那样访问它,这样可以通过索引像 x[p + 1]
直接获取某个元素。
如果你想通过索引查找生成器输出的值,你可以考虑把它转换成一个列表:
x = list(x)
这样可以解决你的问题,并且在大多数情况下都适用。不过,这样做需要一次性生成并保存所有的值,如果你处理的是非常长或者无限的值列表,或者这些值非常大,这样做可能会失败。
如果你只需要生成器中的一个值,你可以使用 itertools.islice(x, p)
来跳过前 p
个值,然后用 next(...)
来获取你需要的那个值。这样就不需要在内存中保存多个项目,也不需要计算超出你所需的值。
import itertools
result = next(itertools.islice(x, p))