Глядя на этот отвечать, кажется, что использование понимания списка (или цикла for
с append
) эквивалентно вызову list(..)
на итераторе. Поскольку генераторы итераторы тоже, я бы ожидал того же от генераторов. Однако если вы запустите
def permute(xs, count, low = 0):
if low + 1 >= count:
yield xs
else:
for p in permute(xs, low + 1):
yield p
for i in range(low + 1, count):
xs[low], xs[i] = xs[i], xs[low]
for p in permute(xs, low + 1):
yield p
xs[low], xs[i] = xs[i], xs[low]
print("Direct iteration")
for x in permute([1, 2], 2):
print(x)
print("Listing")
for x in list(permute([1, 2], 2)):
print(x)
Direct iteration
[1, 2]
[2, 1]
Listing
[1, 2]
[1, 2]
Почему это происходит?
Вы модифицируете и снова и снова получаете один и тот же список xs
. Когда генератор работает, содержимое списка меняется. Похоже, что это работает, потому что, хотя каждый print(x)
печатает один и тот же объект списка, этот объект каждый раз имеет разное содержимое.
С другой стороны, второй цикл запускает генератор до завершения и собирает все ссылки на список. потом он распечатывает списки - за исключением того, что все они один и тот же список, поэтому каждая строка одинакова!
Измените две строки print(x)
на print(x, id(x))
, и вы поймете, что я имею в виду. Идентификационные номера будут идентичны.
Direct iteration
[1, 2] 140685039497928
[2, 1] 140685039497928
Listing
[1, 2] 140685039497736
[1, 2] 140685039497736
Быстрое решение - предоставить копии списка вместо исходного списка. yield p
в порядке, но yield xs
должен стать:
yield xs[:]
После этого исправления результаты такие, как ожидалось:
Direct iteration
[1, 2] 140449546108424
[2, 1] 140449546108744
Listing
[1, 2] 140449546108424
[2, 1] 140449546108808
Одинаковые результаты для обоих контуров, и идентификационные номера разные.