Translate Deleting list item while iterating over it example

This commit is contained in:
Vadim Nifadev 2024-04-23 10:58:11 +03:00
parent 2aa7b37540
commit e8cd593e62
1 changed files with 60 additions and 0 deletions

View File

@ -2120,3 +2120,63 @@ UnboundLocalError: local variable 'a' referenced before assignment
* Прочитайте [это](https://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html) короткое, но потрясающее руководство, чтобы узнать больше о том, как работают пространства имен и разрешение областей видимости в Python.
---
### ▶ Удаление элемента списка во время прохода по списку
<!-- Example ID: 4cc52d4e-d42b-4e09-b25f-fbf5699b7d4e --->
```py
list_1 = [1, 2, 3, 4]
list_2 = [1, 2, 3, 4]
list_3 = [1, 2, 3, 4]
list_4 = [1, 2, 3, 4]
for idx, item in enumerate(list_1):
del item
for idx, item in enumerate(list_2):
list_2.remove(item)
for idx, item in enumerate(list_3[:]):
list_3.remove(item)
for idx, item in enumerate(list_4):
list_4.pop(idx)
```
**Результат:**
```py
>>> list_1
[1, 2, 3, 4]
>>> list_2
[2, 4]
>>> list_3
[]
>>> list_4
[2, 4]
```
Есть предположения, почему вывод `[2, 4]`?
#### 💡 Объяснение:
* Никогда не стоит изменять объект, над которым выполняется итерация. Правильным способом будет итерация по копии объекта, и `list_3[:]` делает именно это.
```py
>>> some_list = [1, 2, 3, 4]
>>> id(some_list)
139798789457608
>>> id(some_list[:]) # Notice that python creates new object for sliced list.
139798779601192
```
**Разница между `del`, `remove` и `pop`:**
* `del var_name` просто удаляет привязку `var_name` из локального или глобального пространства имен (поэтому `list_1` не затрагивается).
* `remove` удаляет первое подходящее значение, а не конкретный индекс, вызывает `ValueError`, если значение не найдено.
* `pop` удаляет элемент по определенному индексу и возвращает его, вызывает `IndexError`, если указан неверный индекс.
**Почему на выходе получается `[2, 4]`?
- Проход по списку выполняется индекс за индексом, и когда мы удаляем `1` из `list_2` или `list_4`, содержимое списков становится `[2, 3, 4]`. Оставшиеся элементы сдвинуты вниз, то есть `2` находится на индексе 0, а `3` - на индексе 1. Поскольку на следующей итерации будет просматриваться индекс 1 (который и есть `3`), `2` будет пропущен полностью. Аналогичное произойдет с каждым альтернативным элементом в последовательности списка.
* Объяснение примера можно найти на [StackOverflow](https://stackoverflow.com/questions/45946228/what-happens-when-you-try-to-delete-a-list-element-while-iterating-over-it).
* Также посмотрите на похожий пример на [StackOverflow](https://stackoverflow.com/questions/45877614/how-to-change-all-the-dictionary-keys-in-a-for-loop-with-d-items), связанный со словарями.
---