Разница между перечислением генератора и циклом - PullRequest
0 голосов
/ 27 сентября 2018

Глядя на этот ответ , кажется, что использование понимания списка (или цикла 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]

Почему это происходит?

1 Ответ

0 голосов
/ 27 сентября 2018

Вы модифицируете и получаете один и тот же список 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

Те же результаты из обоих циклов,и идентификационные номера разные.

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