Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.01.2022, 20:43   #1
Hvv77
Новичок
Джуниор
 
Регистрация: 16.01.2022
Сообщений: 2
По умолчанию Не отрабатывает удаление в цикле всего списка

Всем доброго дня.
У меня Python 3.2.3

Только начал изучать язык Python. Не судите строго, прошу помочь.
В рамках обучения написал прогу которая должна удалять через цикл поочередно элементы из списка.
Код ниже
Код:
print ("Задание 4_1" + "\n")
pizzas = ["4 сыра", "мясная", "маргарита", "овощная"]
print ("Я люблю все " + str(len(pizzas)) + " пиццы!" + "\n")
for pizza in pizzas:
        	pizza = pizzas.pop(0)
	        print ("Пицца " + pizza + " закончилась")
print (pizzas)
Прошу подсказать почему в рамках цикла не удаляются все четыре значения из списка pizzas ?
По результатам отработки кода программы, вижу удаление только 2-х первых элементов и остаток двух последних элементов в списке.

Последний раз редактировалось BDA; 16.01.2022 в 21:50.
Hvv77 вне форума Ответить с цитированием
Старый 16.01.2022, 21:59   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,289
По умолчанию

Не знаю, что именно под капотом "for ... in", но вывод выглядит так, что берется не просто каждый элемент по очереди, а 1й, 2й, 3й, 4й по номерам. Но после двух pop в списке уже нет 3го и 4го элементов. Если нужно вызвать pop столько раз, сколько элементов:
Код:
for _ in range(len(pizzas)):
    pizza = pizzas.pop(0)
    print ("Пицца " + pizza + " закончилась")
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 17.01.2022, 17:34   #3
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,306
По умолчанию

Посмотрел в Сети разные объяснения, но не удовлетворился.
Пробовал менять число элементов списке и получал не стабильный результат, зависящий от длины списка.

Hvv77
Код:
for pizza in pizzas:
    pizza = pizzas.pop(0)
В цикле for набор значений из списка pizzas получает соответствующий набор индексов для последующего выбора.
Состав значений списка меняется методом pop().
То есть, необходимо делать переиндексацию актуального списка, но вероятно это не так.

BDA
Код:
for _ in range(len(pizzas)):
    pizza = pizzas.pop(0)
В этом коде в голове цикла получается только число значений в списке.
Хотя размер списка и меняется, его длинна и, соответственно, набор индексов, не пересчитывается.

Другой способ - не использовать цикл for:
Код:
while pizzas != []:
    print ("Пицца " + pizzas.pop(0) + " закончилась")
Тут просто выбираем все значения из списка.

Вот вопрос: "Можно ли изменить переменную цикла и конечное значение в теле цикла?"
Знаю, что в некоторых языках это делать нельзя явно, например, Ada.
В Python не получится изменять переменную цикла, поскольку на следующем шаге эта переменная получит новое значение из множества значений, формируемых выражением, следующим за in.
Изменять набор значений видимо тоже не следует.

Но, например, в C++ - это как?
Код:
for (int i = 1, i < n, ++i) {
   i = 7;
   n = 15;
...
}
Такое можно, или компилятор ругается?
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 18.01.2022, 01:59   #4
ffuri
Пользователь
 
Регистрация: 18.01.2022
Сообщений: 11
По умолчанию

Цитата:
Сообщение от Hvv77 Посмотреть сообщение
Прошу подсказать почему в рамках цикла не удаляются все четыре значения из списка pizzas ?
Потому что медот pop удаляет элемент из списка и сокращает его длину в каждом цикле на 1, и в связи с этим питон автоматически сокращает цикл на 1, иначе будет исключение IndexEror.
Что бы удалить все элементы с помощью цикла можно сделать через цикл while:
Код:
print ("Задание 4_1" + "\n")
pizzas = ["4 сыра", "мясная", "маргарита", "овощная"]
print ("Я люблю все " + str(len(pizzas)) + " пиццы!" + "\n")
while pizzas:
	pizza = pizzas.pop(0)
	print ("Пицца " + pizza + " закончилась")
print (pizzas)

Последний раз редактировалось ffuri; 18.01.2022 в 02:10.
ffuri вне форума Ответить с цитированием
Старый 18.01.2022, 10:58   #5
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,306
По умолчанию

ffuri
Цитата:
Потому что метод pop удаляет элемент из списка и сокращает его длину в каждом цикле на 1, и в связи с этим питон автоматически сокращает цикл на 1, иначе будет исключение IndexEror.
Не очень понятно, но если посчитать, то получается так:
pop() - сокращает длину списка и уменьшает счётчик числа циклов, который был оценен на входе в цикл. Каждая итерация цикла так же завершается уменьшением счётчика цикла.
Эта интерференция операций и приводит к проблеме.
Примеры:
Код:
Число элементов в списке: 4
Состояние счётчика цикла: 4   2   0 Цикл завершается 
Действие pop(0):          3   1       Выбрано 2-а элемента      Остаток: 2-а элемента
Действие после итерации:  2   0

Число элементов в списке: 7
Состояние счётчика цикла: 7   5   3    1  -1     Цикл завершается 
Действие pop(0):          6   4   2    0           Выбрано 4-е элемента      Остаток: 3-и элемента
Действие после итерации:  5   3   1   -1
PS: Это я больше для себя любимого.
Цикл завершается, если счётчик цикла не больше нуля: <= 0.

PSS: В одной из версий Pascal для DOS была ошибка.
Условием завершения цикла было строгое равенство нулю разности между счётчиком и конечным значением.
Если эта разность становился отрицательной, то цикл продолжался.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 18.01.2022, 11:27   #6
ffuri
Пользователь
 
Регистрация: 18.01.2022
Сообщений: 11
По умолчанию

Цитата:
Сообщение от ViktorR Посмотреть сообщение
Условием завершения цикла было строгое равенство нулю
Ну как то так)) В питоне условием завершения итерации является значение False, т.е. если счетчик больше 0 - True, итерация продолжается, а иначе - False итерация завершается ) (т.е. 0, -1, -2 и т.д. принимают булевое значение False, а все что больше нуля - 1, 2, 3, 4 и т.д. - принимают булевое значение True) =)
И еще можно сделать обратную итерацию если указать в функции range первый параметр start с высоким значением, а второй параметр end меньшим значеним или же можно воспользоваться функцией reversed:
Код:
print ("Задание 4_1" + "\n")
pizzas = ["4 сыра", "мясная", "маргарита", "овощная"]
print ("Я люблю все " + str(len(pizzas)) + " пиццы!" + "\n")
for pizza in reversed(pizzas):
    pizza = pizzas.pop(0)
    print ("Пицца " + pizza + " закончилась")
print (pizzas)

Последний раз редактировалось ffuri; 18.01.2022 в 11:34.
ffuri вне форума Ответить с цитированием
Старый 18.01.2022, 12:47   #7
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,306
По умолчанию

ffuri
Цитата:
Ну как то так)) В питоне условием завершения итерации является значение False, т.е. если счетчик больше 0 - True, итерация продолжается, а иначе - False итерация завершается ) (т.е. 0, -1, -2 и т.д. принимают булевое значение False, а все что больше нуля - 1, 2, 3, 4 и т.д. - принимают булевое значение True) =)
Просто попробуйте, например, так (это к тому, что у вас написано в скобках):
Код:
x = -10
while x:   # Входим в цикл, так как x не ноль
    x += 1
    print(x)
В Python всё что не ноль или не пусто - True.
Именно поэтому вы смогли написать:
Код:
while pizzas:
	pizza = pizzas.pop(0)
	print ("Пицца " + pizza + " закончилась")
Как только список стал пустым - вываливаемся.
В моём, предшествующем вашему посту примере, сделана проверка на пустоту, но это только для ясности.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 22.01.2022, 07:29   #8
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,289
По умолчанию

Цитата:
Сообщение от ViktorR Посмотреть сообщение
Но, например, в C++ - это как? Такое можно, или компилятор ругается?
Только не запятые, а точки с запятой. Да, вроде, можно. Компилятор не ругается. Ну не считая получившего бесконечного цикла.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 22.01.2022, 13:14   #9
Hvv77
Новичок
Джуниор
 
Регистрация: 16.01.2022
Сообщений: 2
По умолчанию

Спасибо всем за участие и помощь в решении задачки!!!
Hvv77 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
удаление элемента односвязного списка. язык СИ. всего 5 строчек кода, много времени не займет. MisterTreb Помощь студентам 0 08.01.2013 15:17
Удаление всего кроме формул Severny Microsoft Office Excel 21 13.07.2011 12:22
listview свойство типа data, только для всего списка boshki Общие вопросы Delphi 1 05.06.2011 12:56
Удаление последнего элемента из списка и реверс этого списка. Goose Общие вопросы C/C++ 8 16.05.2010 16:12
Элементы списка, выведенные в цикле, скрываются Svetix PHP 5 24.04.2009 15:06