- The syntax
- The break and continue command for loops
- The use of break, continue, else, and while
- The for loops and mutable collections
Earlier, we looked at while
loops. This construction repeats a set of actions. Anything beyond repetition requires additional means of storing the state.
Here, we will take the counter that we change in the loop as an example. When working with collections, we choose which item we're working on within the current iteration. So should we use a variable counter every time?
All programmers want to automate routine work, and language writers are no exception. That's why Python has a different kind of loop for working with collections — the for
loop.
It's worth noting that this loop isn't like loops with the same name in other programming languages. This loop is just a supplement to the variable-counter loop termination condition in many languages.
Python has gone further, so in this language, the for
loop immediately goes through the elements of the input collection, and you often don't need to think about the index at all.
The syntax
The for
loop is simple:
for element in collection:
print(element) # This is the body of the cycle
Note that loops don't have an explicit termination condition in the simplest case. The loop stops when the collection runs out of items.
The example above will work for tuples and lists. In this case, we will see all elements. And you can also iterate — traverse a collection. In this case, the loop variable element
will contain all characters of the string in turn:
for c in 'Hello!':
print(c)
# => H
# => e
# => l
# => l
# => o
# => !
But what do we do when we need to get the list of items one by one and change those items? After all, we need the index of each element.
Python has the handy enumerate
function for this. This function provides each element with an index and puts them into a tuple together. These tuples are usually unpacked right in the first string of the loop:
items = ['foo', 'bar', 'baz']
for (index, elem) in enumerate(items):
items[index] = elem + '!'
print(items) # => ['foo!', 'bar!', 'baz!']
In this loop, we replaced each element with the original value, with the string '!'
added at the end. We can write this code in a slightly different way:
items = ['foo', 'bar', 'baz']
for (index, _) in enumerate(items):
items[index] += '!'
print(items) # => ['foo!', 'bar!', 'baz!']
This time we use only indexes. Therefore, we have an underscore instead of the loop variable into which we packed the elements.
It isn't some specific variable, just a convention. In Python, you often write insignificant things to the variable _
in this context.
Note the last example did talk about indexes, but we still didn't use the collection length. The enumerate
function also knows where to stop: at the end of the original collection.
The break
and continue
command for loops
Sometimes you don't have to get to the end of the collection. For example, when searching for an element that satisfies a condition. Once we've found the first suitable element, we would do well to save resources and finish the loop.
We do this early exit from the loop using the break
command.
Here's a loop to find the first positive number:
items = [-2, 0, -10, 3, 5, -1]
for item in items:
if item > 0:
break
print(item) # => 3
As you may have noticed, the loop variable was available even after the loop ended. However, if the collection is empty, Python will not define the variable — keep this in mind.
This code seems to work as it should. However, if there's no positive number in the list, the item
variable will contain only the last item from the list.
So how do we know we haven't found anything? The else
is here to help. It is executed in the loop if break
doesn't get used. It is perfect for search algorithms. Let's rewrite our example using else
:
items = [-2, 0, -10, -1]
for item in items:
if item > 0:
break
else:
item = None
print(item) # => None
Now suppose we realized during the execution of the loop body that there's no need to execute the rest of the body and that we can proceed immediately to the next iteration.
Use the command continue
to go to the next iteration. We read strings containing lines of code, but we don't need to process the code from lines that begin with the #
symbol.
It is what the code will look like:
lines_of_code = [
'# begin of example',
'echo 123',
'cd foo',
'# end']
for line in lines_of_code:
if line[:1] == '#':
continue
# We process the code here
print(line)
# => echo 123
# => cd foo
Of course, a conventional construction wouldn't hurt. In this case, the code that handles the necessary strings would be nested deeper. And we should try to keep the nesting of code within reasonable limits. Otherwise, the code will very quickly become very difficult to read.
The use of break
, continue
, else
, and while
The else
branch and the break
and continue
commands are also available for the while
loop. Here's a comprehensive example that demonstrates all these abilities:
tries_count = 3
while tries_count:
print('>>> ', end='')
command = input()
if not command:
continue
if command in ('echo', 'cd', 'help'):
break
print('Unknown command!')
tries_count -= 1
else:
print('Too many bad tries!')
command = None
This code asks the user to enter one of the commands, ignores blank input, and limits the number of attempts to enter a command. Think about which part of the loop body is responsible for what.
The for
loops and mutable collections
We advise you not to change the list composition while iterating in the `for' loop. If you remove items from the list you're traversing or even add new ones at the end, the result can be unexpected, up to and including an error crashing the program. It is better to fill a new list while traversing the old one.
If you want to change the composition of the original list, then traverse the copy of the list in another loop:
for x in original_list[:]:
original_list.pop(0)
You can also create a temporary list, clear the original one and add items from the temporary one:
new_list = []
for x in original_list:
...
original_list[:] = [] # Removing the old content
original_list.extend(new_list)
Of course, you can combine these two options:
- First, make a copy
- Then clear the original
- And then add new elements in a loop that traverses the copy
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.