rspec/rules/S6417/python/rule.adoc

47 lines
2.0 KiB
Plaintext
Raw Normal View History

2023-08-04 16:47:45 +02:00
This rule raises an issue when a method modifies the size of a collection, while the same collection is iterated.
== Why is this an issue?
2023-08-04 16:47:45 +02:00
Iterating over a collection using a `for` loop in Python relies on iterators.
2023-08-04 16:47:45 +02:00
An iterator is an object that allows you to traverse a collection of elements, such as a list or a dictionary. Iterators are used in `for` loops to iterate over the elements of a collection one at a time.
When you create an iterator, it keeps track of the current position in the collection and provides a way to access the next element. The `next()` function is used to retrieve the next element from the iterator. When there are no more elements to iterate over, the `next()` function raises a StopIteration exception and the iteration stops.
It is important to note that iterators are designed to be read-only. Modifying a collection while iterating over it can cause unexpected behavior, as the iterator may skip over or repeat elements. A `RuntimeError` may also be raised in this situation, with the message `changed size during iteration`. Therefore, it is important to avoid modifying a collection while iterating over it to ensure that your code behaves as expected.
2023-08-04 16:47:45 +02:00
If you still want to modify the collection, it is best to use a second collection or to iterate over a copy of the original collection instead.
2023-08-04 16:47:45 +02:00
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
def my_fun():
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key in my_dict:
2023-08-04 16:47:45 +02:00
if my_dict[key] == 'foo':
my_dict.pop(key) # Noncompliant: this will make the iteration unreliable
----
=== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
def my_fun():
my_dict = {'a': 1, 'b': 2, 'c': 3}
2023-08-04 16:47:45 +02:00
for key in list(my_dict.keys()):
if my_dict[key] == 'foo':
my_dict.pop(key)
----
== Resources
=== Documentation
* Python Documentation - https://docs.python.org/3/tutorial/controlflow.html#for-statements[`for` Statements]