10 Iterations
In this section we’ll explore reiteration using iterable objects and iterators
We got already pretty far in our Python journey without looking at looping. That’s not because it’s not necessary or useful, but we needed to get a solid foundation on the basic concepts first. Let’s take a look at iterations here.
10.1 Iterators
The most common type of iteration is the for loop
. Like functions indentation is with 4 spaces, not a tab.
We can iterate over elements in a list:
# Display names in a list:
= ['A', 'B', 'C'] letters
for names in letters:
print(names)
#> A
#> B
#> C
Over characters in a string
# Characters in a string
for letter in 'Rick':
print(letter)
#> R
#> i
#> c
#> k
Or over a sequence of numbers
# over a sequence of numbers
for i in range(4):
print(i)
#> 0
#> 1
#> 2
#> 3
This is because list, strings and ranges are all iterable objects, but so are dictionaries and even file connections. All that means is that these objects have an associated iter()
method.
An iterator is an object that has an associated next()
method. To create an iterator from iterable, use the Builtin iter()
function:
To summarize:
- An iterable is an object that can return an iterator
- An iterator is an object that keeps state and produces the next value when you call
next()
on it.
= 'Python'
word
= iter(word)
it
next(it)
#> 'P'
next(it)
#> 'y'
next(it)
#> 't'
next(it)
#next(it)
#> 'h'
After the fourth iteration there are no more steps, we get a StopIteration
error.
We can print all values of an iterator in one go with the star (aka “splat”) operator *
.
= 'Python'
word
= iter(word)
it
print(*it)
#> P y t h o n
print(*it)
But you can only do it once.
Recall that dictionaries are also iterables. The items()
method unpacks the items in a dictionary into key/value pairs. We loop over two items then, and separate them using a comma.
= {'Rick': 'Scavetta', 'Mary': 'Shelly'}
people
for key, value in people.items():
print(key, value)
#> Rick Scavetta
#> Mary Shelly
We can also loop over elements in files (not executed):
file = 'open.txt'
= iter(file)
it
print(next(it))
print(next(it))
We can use the iter()
function to get an iterator, as well as the next()
function to retrieve the values one by one from the iterator.
Some functions can take iterators and iterables as arguments, like list()
and sum()
.
# Create a range object: values
= range(10, 21) values
# Print the range object
values#> range(10, 21)
# Create a list of integers: values_list
= list(values) values_list
# Print values_list
values_list#> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
# Get the sum of values: values_sum
= sum(values) values_sum
# Print values_sum
values_sum#> 165
10.1.1 Common functions when working with iterables
Two functions that you’ll encounter when using iterables are:
-
enumerate()
, to add a counter to any iterable, and -
zip()
, to stitch together an arbitrary number of iterables.
For example, to add a counter:
= ['A', 'B', 'C']
names = enumerate(names)
e print(type(e))
#> <class 'enumerate'>
This consists of pairs containing the original values and their index position. To see what that means, use list()
to convert this to a list of tuples.
= list(e)
e_list
e_list#> [(0, 'A'), (1, 'B'), (2, 'C')]
Actually, the enumerate object is itself an iterable and we can loop over it. Notice how we use two values for looping, like we did with dictionaries.
= ['A', 'B', 'C', 'D', 'E', 'F']
names
for index, value in enumerate(names):
print(index, value)
#> 0 A
#> 1 B
#> 2 C
#> 3 D
#> 4 E
#> 5 F
We can even control the stating of the index using the start argument:
for index, value in enumerate(names, start = 3):
print(index, value)
#> 3 A
#> 4 B
#> 5 C
#> 6 D
#> 7 E
#> 8 F
To summaries, enumerate()
returns an enumerate object that produces a sequence of tuples, and each of the tuples is an index/value pair.
We’ve already seen zip()
in action. This function accepts an arbitrary number of iterables and returns an iterator of tuples. For example, with two lists:
= ['A', 'B', 'C', 'D', 'E', 'F']
letter = ['Aardvark', 'Bear', 'Cat', 'Dog', 'Elephant', 'Fox']
names
= zip(letter, names)
z
# type(z)
## <class 'zip'>
z#> <zip object at 0x288baa280>
Alternatively:
for z1, z2 in zip(letter, names):
print(z1, z2)
#> A Aardvark
#> B Bear
#> C Cat
#> D Dog
#> E Elephant
#> F Fox
Exercise 10.1 Get a unique list of values in the group column of plant_growth. Previously we just used the .groupby() to apply an aggregration function to the weights, as an example of doing this manually, loop through the DataFrame and calculate the mean weight according to each group.