@@ -5,33 +5,33 @@ So far we have used for loops with many different kinds of things.
5
5
``` py
6
6
>> > for name in [' theelous3' , ' RubyPinch' , ' go|dfish' ]:
7
7
... print (name)
8
- ...
8
+ ...
9
9
theelous3
10
10
RubyPinch
11
11
go| dfish
12
12
>> > for letter in ' abc' :
13
13
... print (letter)
14
- ...
14
+ ...
15
15
a
16
16
b
17
17
c
18
- >> >
18
+ >> >
19
19
```
20
20
21
- For looping over something is one way to ** iterate** over it. Some other
22
- things also iterate, for example, ` ' '.join(['a', 'b', 'c']) ` iterates
23
- over the list ` ['a', 'b', 'c'] ` . If we can for loop over something, then
24
- that something is ** iterable** . For example, strings and lists are
21
+ For looping over something is one way to ** iterate** over it. Some other
22
+ things also iterate, for example, ` ' '.join(['a', 'b', 'c']) ` iterates
23
+ over the list ` ['a', 'b', 'c'] ` . If we can for loop over something, then
24
+ that something is ** iterable** . For example, strings and lists are
25
25
iterable, but integers and floats are not.
26
26
27
27
``` py
28
28
>> > for thing in 123 :
29
29
... print (thing)
30
- ...
30
+ ...
31
31
Traceback (most recent call last):
32
32
File " <stdin>" , line 1 , in < module>
33
33
TypeError : ' int' object is not iterable
34
- >> >
34
+ >> >
35
35
```
36
36
37
37
## Iterators
@@ -42,36 +42,36 @@ Lists and strings don't change when we iterate over them.
42
42
>> > word = ' hi'
43
43
>> > for character in word:
44
44
... print (character)
45
- ...
45
+ ...
46
46
h
47
47
i
48
48
>> > word
49
49
' hello'
50
- >> >
50
+ >> >
51
51
```
52
52
53
- We can also iterate over [ files] ( ../basics/files.md ) , but they change
54
- when we do that. They remember their position, so if we iterate over
53
+ We can also iterate over [ files] ( ../basics/files.md ) , but they change
54
+ when we do that. They remember their position, so if we iterate over
55
55
them twice we get the content once only.
56
56
57
57
``` py
58
58
>> > with open (' test.txt' , ' w' ) as f:
59
59
... print (" one" , file = f)
60
60
... print (" two" , file = f)
61
- ...
61
+ ...
62
62
>> > a = []
63
63
>> > b = []
64
64
>> > with open (' test.txt' , ' r' ) as f:
65
65
... for line in f:
66
66
... a.append(line)
67
67
... for line in f:
68
68
... b.append(line)
69
- ...
69
+ ...
70
70
>> > a
71
71
[' one\n ' , ' two\n ' ]
72
72
>> > b
73
73
[]
74
- >> >
74
+ >> >
75
75
```
76
76
77
77
We have also used [ enumerate] ( ../basics/trey-hunner-zip-and-enumerate.md )
@@ -81,21 +81,21 @@ before, and it actually remembers its position also:
81
81
>> > e = enumerate (' hello' )
82
82
>> > for pair in e:
83
83
... print (pair)
84
- ...
84
+ ...
85
85
(0 , ' h' )
86
86
(1 , ' e' )
87
87
(2 , ' l' )
88
88
(3 , ' l' )
89
89
(4 , ' o' )
90
90
>> > for pair in e:
91
91
... print (pair)
92
- ...
93
- >> >
92
+ ...
93
+ >> >
94
94
```
95
95
96
- Iterators are ** iterables that remember their position** . For example,
97
- ` open('test.txt', 'r') ` and ` enumerate('hello') ` are iterators.
98
- Iterators can only be used once, so we need to create a new iterator if
96
+ Iterators are ** iterables that remember their position** . For example,
97
+ ` open('test.txt', 'r') ` and ` enumerate('hello') ` are iterators.
98
+ Iterators can only be used once, so we need to create a new iterator if
99
99
we want to do another for loop.
100
100
101
101
Here's a picture that hopefully explains this better:
@@ -104,8 +104,8 @@ Here's a picture that hopefully explains this better:
104
104
105
105
## Iterating manually
106
106
107
- Iterators have a magic method called ` __next__ ` , and there's a built-in
108
- function called ` next() ` for calling that. Calling ` next() ` on an
107
+ Iterators have a magic method called ` __next__ ` , and there's a built-in
108
+ function called ` next() ` for calling that. Calling ` next() ` on an
109
109
iterator gets the next value and moves it forward. Like this:
110
110
111
111
``` py
@@ -116,7 +116,7 @@ iterator gets the next value and moves it forward. Like this:
116
116
(1 , ' b' )
117
117
>> > e.__next__ ()
118
118
(2 , ' c' )
119
- >> >
119
+ >> >
120
120
```
121
121
122
122
There's also a built-in ` next() ` function that does the same thing:
@@ -129,26 +129,26 @@ There's also a built-in `next()` function that does the same thing:
129
129
(1 , ' b' )
130
130
>> > next (e)
131
131
(2 , ' c' )
132
- >> >
132
+ >> >
133
133
```
134
134
135
- Here ` e ` remembers its position, and every time we call ` next(e) ` it
136
- gives us the next element and moves forward. When it has no more values
135
+ Here ` e ` remembers its position, and every time we call ` next(e) ` it
136
+ gives us the next element and moves forward. When it has no more values
137
137
to give us, calling ` next(e) ` raises a StopIteration:
138
138
139
139
``` py
140
140
>> > next (e)
141
141
Traceback (most recent call last):
142
142
File " <stdin>" , line 1 , in < module>
143
143
StopIteration
144
- >> >
144
+ >> >
145
145
```
146
146
147
- There is usually not a good way to check if the iterator is at the end,
148
- and it's best to just try to get an value from it and catch
147
+ There is usually not a good way to check if the iterator is at the end,
148
+ and it's best to just try to get an value from it and catch
149
149
StopIteration.
150
150
151
- This is actually what for looping over an iterator does. For example,
151
+ This is actually what for looping over an iterator does. For example,
152
152
this code...
153
153
154
154
``` py
@@ -170,24 +170,24 @@ while True:
170
170
print (pair)
171
171
```
172
172
173
- The for loop version is much simpler to write and I wrote the while loop
173
+ The for loop version is much simpler to write and I wrote the while loop
174
174
version just to explain what the for loop does.
175
175
176
176
## Converting to iterators
177
177
178
- Now we know what iterating over an iterator does. But how about
179
- iterating over a list or a string? They are not iterators, so we can't
178
+ Now we know what iterating over an iterator does. But how about
179
+ iterating over a list or a string? They are not iterators, so we can't
180
180
call ` next() ` on them:
181
181
182
182
``` py
183
183
>> > next (' abc' )
184
184
Traceback (most recent call last):
185
185
File " <stdin>" , line 1 , in < module>
186
186
TypeError : ' str' object is not an iterator
187
- >> >
187
+ >> >
188
188
```
189
189
190
- There's a built-in function called ` iter() ` that converts anything
190
+ There's a built-in function called ` iter() ` that converts anything
191
191
iterable to an iterator.
192
192
193
193
``` py
@@ -204,7 +204,7 @@ iterable to an iterator.
204
204
Traceback (most recent call last):
205
205
File " <stdin>" , line 1 , in < module>
206
206
StopIteration
207
- >> >
207
+ >> >
208
208
```
209
209
210
210
Calling ` iter() ` on anything non-iterable gives us an error.
@@ -214,17 +214,17 @@ Calling `iter()` on anything non-iterable gives us an error.
214
214
Traceback (most recent call last):
215
215
File " <stdin>" , line 1 , in < module>
216
216
TypeError : ' int' object is not iterable
217
- >> >
217
+ >> >
218
218
```
219
219
220
- If we try to convert an iterator to an iterator using ` iter() ` we just
220
+ If we try to convert an iterator to an iterator using ` iter() ` we just
221
221
get back the same iterator.
222
222
223
223
``` py
224
224
>> > e = enumerate (' abc' )
225
225
>> > iter (e) is e
226
226
True
227
- >> >
227
+ >> >
228
228
```
229
229
230
230
So code like this...
@@ -248,8 +248,8 @@ while True:
248
248
249
249
## Custom iterables
250
250
251
- Implementing a custom iterator is easy. All we need to do is to define a
252
- ` __next__ ` method that gets the next element, and an ` __iter__ ` method
251
+ Implementing a custom iterator is easy. All we need to do is to define a
252
+ ` __next__ ` method that gets the next element, and an ` __iter__ ` method
253
253
that returns the iterator itself. For example, here's an iterator that
254
254
behaves like ` iter([1, 2, 3]) ` :
255
255
0 commit comments