【问题标题】:"'generator' object is not subscriptable" error“‘生成器’对象不可下标”错误
【发布时间】:2011-09-11 09:28:09
【问题描述】:

为什么我在尝试解决 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

【问题讨论】:

    标签: python generator


    【解决方案1】:

    您的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))
    

    【讨论】:

    • Python 的“列表”更接近于数组,而不是大多数其他语言所称的列表。它们会自动调整数组的大小(许多语言称之为“向量”,甚至简称为“数组”)。它们不是链表,它们支持任何元素的常量类型查找,而不仅仅是头部,这与大多数语言中的“列表”不同。
    • 应该提到,将生成器转换为列表与生成器的初始用例(例如节省内存)相矛盾,这可能会使这样的解决方案无用。
    【解决方案2】:

    作为 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:]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 2019-02-10
      • 2012-04-04
      相关资源
      最近更新 更多