Чтобы понять, как работает этот код, вам необходимо понять:
1) повторяемый объект?
2) итератор?
3) Протокол итерации
4) генератор?
5) Как работает генератор?
Позвольте мне дать представление о каждом из них:
Итерируемый : Итерируемым является любой объект в Python, для которого определен метод iter или getitem , который возвращает итератор или может принимать индексы. В основном объект по которому мы можем запустить цикл.
например:
>>> for i in [1,2,3]:
print(i)
1
2
3
здесь у нас есть список как итеративный объект, элементы которого можно индексировать и извлекать с помощью индекса.
>>> for i in {x:1,y:2}:
print(x)
х
у
здесь у нас есть словарь как итеративный объект, он перебирает свои ключи.
Итератор : Итератор - это любой объект в Python, для которого определен метод next (Python2) или next . Это оно. Это итератор.
Протокол итерации : встроенная функция iter принимает итеративный объект и возвращает итератор.
>>> x = iter([1, 2, 3])
>>> x
<listiterator object at 0x1004ca850>
>>> x.next()
1
>>> x.next()
2
>>> x.next()
3
>>> x.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Генератор : Генераторы являются итераторами, но вы можете перебирать их только один раз. Потому что они не хранят все значения в памяти, они генерируют значения на лету.
Например:
def yrange(n):
i = 0
while i < n:
yield i
i += 1
Каждый раз, когда выполняется оператор yield, функция генерирует новое значение.
>>> y = yrange(3)
>>> y
<generator object yrange at 0x401f30>
>>> y.next()
0
>>> y.next()
1
>>> y.next()
2
>>> y.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Таким образом, генератор также является итератором.
Примечание. Каждый раз, когда вызывается next (), он возобновляет работу с того места, где остановился (он запоминает все значения данных и какой оператор был выполнен в последний раз).
Другой ключевой особенностью является то, что локальные переменные и состояние выполнения автоматически сохраняются между вызовами.
Давайте разберемся с этим на примере:
>>> def foo():
print "begin"
for i in range(3):
print "before yield", i
yield i
print "after yield", i
print "end"
>>> f = foo()
>>> f.next()
begin
before yield 0
0
>>> f.next()
after yield 0
before yield 1
1
>>> f.next()
after yield 1
before yield 2
2
>>> f.next()
after yield 2
end
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Теперь перейдем к вашей проблеме:
M = [[1,2,3], #M is iterable object
[4,5,6],
[7,8,9]]
G = (sum(row) for row in M) # creates a generator of row sums
next(G) # Run the iteration protocol