1

在 Python...

我在一个类中定义了一个嵌套列表:

self.env = [[ None for i in range(columnCount)] for j in range(rowCount) ]       

出于这个问题的目的,让我们假设这个嵌套列表包含以下值:

[None, None, None, None]
[None, None, None, None]
[None, None, 0, None]
[None, None, None, None]

我需要能够利用iter和 next() 方法以列主要顺序(row0、col0、row1、col0、row2、col0 ...)来遍历此列表。

目的是让它将位于该网格位置的值发送到另一个函数以进行处理。

到目前为止,我将iter函数定义为:

def __iter__(self):
    return iter(self.env)

然后我将下一个函数定义为:

def next(self):
    self.currentRow += 1
    self.currentColumn += 1

    if ( (self.currentRow < self.getRowCount()) and (self.currentColumn < self.getColumnCount()) ):
        return self.env[self.currentRow][self.currentColumn]
    else:
        raise StopIteration

我遇到的问题是,似乎iter函数将每一行作为列表返回,但它没有调用下一个方法来进一步处理该列表。

我的目标是逐个打印每个网格位置的值......如:

无 无 ... 无 0 无 ... 无

有人可以详细说明为了实现这一目标我缺少什么吗?

4

3 回答 3

2

你可能正在以一种过于复杂的方式接近。

我会以这种方式解决这个问题:

  • 再举一个例子——你的对调是对称的,所以你看不到做错的效果。让我们来

    x = [[1, 2, 3, 4], [5, 6, 7, 8]]
    

目前。

  • 使用zip()or (对于大列表)可能更好地itertools.izip()转置它,并删除一个级别:

    y = [j for i in itertools.izip(*x) for j in i]
    

    在这里,izip()迭代所有给定的列表并组合它们的第一个、第二个、...元素以生成元组(1, 5), (2, 6)等等。i遍历这些元组,遍历j它们的项目。y也是如此[1, 5, 2, 6, 3, 7, 4, 8]

  • 现在,如果您希望您的类实例以这种方式可迭代,您可以采用以下几种方法:

    • 您可以__iter__()是生成器函数或返回迭代器,例如

      def __iter__(self): return (j for i in itertools.izip(*self.env) for j in i)
      def __iter__(self):
          for i in itertools.izip(*self.env):
              for j in i: yield i
      def __iter__(self): return iter([j for i in itertools.izip(*self.env) for j in i])
      

      等等。这样,您的对象是可迭代的,但不是迭代器。

    • 您可以如您所愿,让您的对象成为它自己的迭代器,并让__iter__()返回self并实现一个next(). 然而,我反对这一点,因为

      • 您需要自己跟踪索引
      • 一旦用尽,您可以(并且不应该)重新启动此迭代器,您可以在此处阅读:

        [...] 一旦迭代器的 next() 方法引发 StopIteration,它将在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。(此约束是在 Python 2.3 中添加的;在 Python 2.2 中,根据此规则破坏了各种迭代器。)

        因此,每次迭代都需要一个新对象。

    • 你甚至可以用 来做一些有趣的事情__getitem__(),因为是 Python 的“最后手段”,如果它本身不提供迭代器,它可以使对象可迭代,正如PEP234所提议的那样:

      def __getitem__(self, index):
          if index >= len(self): raise IndexError
          # do a complicated calculation to map from this single index to your `self.env`
      def __len__(self): # not needed, but handy
          return sum(len(i) for i in self.env)
      
于 2012-10-18T07:01:56.170 回答
1

您的__iter__函数正在返回iter(self.env),它返回 self.env 的迭代器。如果你想调用你的下一个方法__iter__,你应该返回self。但是您的实现中还有其他问题,例如,您的迭代器不会多次工作。

有更简单的方法可以实现这一点。您可以编写生成器表达式/列表理解来实现此目的(请参阅@Eric 的答案)。您还可以编写生成器方法。例如:

def iter_column_row():
    for i in range(self.getColumnCount()):
        for j in range(self.getRowCount()):
            yield self.env[j][i]
于 2012-10-18T06:56:48.570 回答
0
def __iter__(self):
    return (self.env[j][i] for i in range(columnCount)
                           for j in range(rowCount))

可能需要交换 I 和 j

于 2012-10-18T06:41:43.103 回答