двойной итератор в одном объекте python - PullRequest
2 голосов
/ 22 июня 2009

В python я пытаюсь написать класс, который поддерживает два разных типа итераторов. Грубо говоря, этот объект содержит матрицу данных, и я хочу иметь два разных типа итераторов для поддержки итерации строк и итераций столбцов.

Ответы [ 3 ]

5 голосов
/ 22 июня 2009

dict имеет несколько методов создания итераторов - iterkeys, itervalues, iteritems - и ваш класс тоже. Если есть один «самый естественный» способ итерации, вы должны также присвоить ему псевдоним __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
4 голосов
/ 22 июня 2009

Это то, что вы ищете?

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, если хотите создать каждый столбец по требованию.

Вы также можете переместить итерацию фактических значений в класс. Я не был уверен, хотите ли вы перебрать строки / столбцы (как показано) или значения в строк / столбцов.

2 голосов
/ 22 июня 2009

Хорошо, так что сделайте два отдельных метода, каждый из которых является генератором.

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__.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...