一个Python对象中的双迭代器

2 投票
3 回答
863 浏览
提问于 2025-04-15 12:25

在Python中,我想写一个类,这个类可以支持两种不同的迭代器。简单来说,这个对象里面包含了一组数据矩阵,我想要有两种不同的迭代器,分别用来按行和按列进行遍历。

3 个回答

2

好的,先创建两个单独的方法,每个方法都是一个生成器。

class Matrix(object):
    def iter_rows(self):
        for row in self.rows:
            yield row

    def iter_columns(self):
        for column in self.columns:
            yield column

你的 __iter__ 方法可以默认遍历其中一个生成器,不过我建议干脆不写 __iter__ 方法。

4

这就是你想要的东西吗?

class Matrix(object):
    def __init__(self, rows):
        self._rows = rows

    def columns(self):
        return zip(*self._rows)

    def rows(self):
        return self._rows

# Create a Matrix by providing rows.
m = Matrix([[1,2,3],
            [4,5,6],
            [7,8,9]])

# Iterate in row-major order.
for row in m.rows():
    for value in row:
        print value

# Iterate in column-major order.
for column in m.columns():
    for value in column:
        print value

如果你想要按需创建每一列,可以用 itertools.izip 来代替 zip

你也可以把实际值的遍历放到类里面。我不太确定你是想遍历行/列(像这样)还是想遍历行/列里面的值。

5

dict(字典)有几种方法可以用来生成迭代器,比如 iterkeysitervaluesiteritems。你的类也应该有类似的功能。如果有一种“最自然”的迭代方式,你应该把它也命名为 __iter__,这样使用起来更方便、更易读(通常这可能是 iterrows;当然,在设计 dict 的迭代行为时也会有一些疑问,但选择一个合理的方式总比没有好)。

举个例子,假设你的矩阵是方形的,数据被压缩成一个行优先的列表 self.data,边长为 self.n。那么:

def iterrows(self):
  start = 0
  n = self.n
  data = self.data
  while start < n*n:
    stop = start + n
    yield data[start:stop]
    start = stop

def itercols(self):
  start = 0
  n = self.n
  data = self.data
  while start < n:
    yield data[start::n]
    start += 1

__iter__ = iterrows

撰写回答