Разница между перечислением генератора и циклом

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

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
48
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

Другие вопросы по теме