Skip to content

Commit c2ac9c6

Browse files
committed
new "advanced" section and reorganizing everything for it
1 parent 719fee5 commit c2ac9c6

27 files changed

+860
-521
lines changed

README.md

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,53 @@ everything should also work on Python 3.3, 3.2 and all newer Pythons.
2323

2424
## List of contents
2525

26-
1. [What is programming?](what-is-programming.md)
27-
2. [Installing Python](installing-python.md)
28-
3. [Getting started with Python](getting-started.md)
29-
4. [ThinkPython: The way of the program](the-way-of-the-program.md)
30-
5. [Variables, Booleans and None](variables.md)
31-
6. [Using functions](using-functions.md)
32-
7. [If, else and elif](if.md)
33-
8. [Handy stuff with strings](handy-stuff-strings.md)
34-
9. [Lists and tuples](lists-and-tuples.md)
35-
10. [Loops](loops.md)
36-
11. [Trey Hunner: zip and enumerate](trey-hunner-zip-and-enumerate.md)
37-
12. [Dictionaries](dicts.md)
38-
13. [Defining functions](defining-functions.md)
39-
14. [What is true?](what-is-true.md)
40-
15. [Files](files.md)
41-
16. [Exceptions](exceptions.md)
42-
17. [Modules](modules.md)
43-
18. [Classes](classes.md)
44-
45-
Other things this tutorial comes with:
26+
The tutorial consists of two sections:
27+
28+
### Basics
29+
30+
This section will get you started with using Python and you'll be able
31+
to learn more about whatever you want after studying it.
32+
33+
1. [What is programming?](basics/what-is-programming.md)
34+
2. [Installing Python](basics/installing-python.md)
35+
3. [Getting started with Python](basics/getting-started.md)
36+
4. [ThinkPython: The way of the program](basics/the-way-of-the-program.md)
37+
5. [Variables, Booleans and None](basics/variables.md)
38+
6. [Using functions](basics/using-functions.md)
39+
7. [If, else and elif](basics/if.md)
40+
8. [Handy stuff with strings](basics/handy-stuff-strings.md)
41+
9. [Lists and tuples](basics/lists-and-tuples.md)
42+
10. [Loops](basics/loops.md)
43+
11. [Trey Hunner: zip and enumerate](basics/trey-hunner-zip-and-enumerate.md)
44+
12. [Dictionaries](basics/dicts.md)
45+
13. [Defining functions](basics/defining-functions.md)
46+
14. [What is true?](basics/what-is-true.md)
47+
15. [Files](basics/files.md)
48+
16. [Exceptions](basics/exceptions.md)
49+
17. [Modules](basics/modules.md)
50+
18. [Classes](basics/classes.md)
51+
52+
### Advanced
53+
54+
If you want to learn more advanced techniques, you can also read this
55+
section. Most of the techniques explained here are great when you're
56+
working on a large project, and your code would be really repetitive
57+
without these things.
58+
59+
You can experient with these things freely, but please **don't use these
60+
techniques just because you know how to use them.** Prefer the simple
61+
techniques from the Basics part instead when possible. Simple is better
62+
than complex.
63+
64+
1. [Iterables and iterators](advanced/iterators.md)
65+
66+
### Other things this tutorial comes with
4667

4768
- **Important:** [getting help](getting-help.md)
4869
- [Contact me](contact-me.md)
4970
- [Setting up a text editor](editor-setup.md)
50-
- [Answers for the exercises](answers.md)
71+
- Answers for excercises in [basics](basics/answers.md) and
72+
[advanced](advanced/answers.md) sections
5173
- [The TODO list](TODO.md)
5274

5375
## How to read this tutorial without an internet connection

advanced/answers.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
***
3+
4+
You may use this tutorial freely at your own risk. See
5+
[LICENSE](../LICENSE).
6+
7+
[List of contents](../README.md#list-of-contents)

advanced/iterators.md

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
# Iterables and iterators
2+
3+
So far we have used for loops with many different kinds of things.
4+
5+
```py
6+
>>> for name in ['theelous3', 'RubyPinch', 'go|dfish']:
7+
... print(name)
8+
...
9+
theelous3
10+
RubyPinch
11+
go|dfish
12+
>>> for letter in 'abc':
13+
... print(letter)
14+
...
15+
a
16+
b
17+
c
18+
>>>
19+
```
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
25+
iterable, but integers and floats are not.
26+
27+
```py
28+
>>> for thing in 123:
29+
... print(thing)
30+
...
31+
Traceback (most recent call last):
32+
File "<stdin>", line 1, in <module>
33+
TypeError: 'int' object is not iterable
34+
>>>
35+
```
36+
37+
## Iterators
38+
39+
Lists and strings don't change when we iterate over them.
40+
41+
```py
42+
>>> word = 'hi'
43+
>>> for character in word:
44+
... print(character)
45+
...
46+
h
47+
i
48+
>>> word
49+
'hello'
50+
>>>
51+
```
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
55+
them twice we get the content once only.
56+
57+
```py
58+
>>> with open('test.txt', 'w') as f:
59+
... print("one", file=f)
60+
... print("two", file=f)
61+
...
62+
>>> a = []
63+
>>> b = []
64+
>>> with open('test.txt', 'r') as f:
65+
... for line in f:
66+
... a.append(line)
67+
... for line in f:
68+
... b.append(line)
69+
...
70+
>>> a
71+
['one\n', 'two\n']
72+
>>> b
73+
[]
74+
>>>
75+
```
76+
77+
We have also used [enumerate](../basics/trey-hunner-zip-and-enumerate.md)
78+
before, and it actually remembers its position also:
79+
80+
```py
81+
>>> e = enumerate('hello')
82+
>>> for pair in e:
83+
... print(pair)
84+
...
85+
(0, 'h')
86+
(1, 'e')
87+
(2, 'l')
88+
(3, 'l')
89+
(4, 'o')
90+
>>> for pair in e:
91+
... print(pair)
92+
...
93+
>>>
94+
```
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
99+
we want to do another for loop.
100+
101+
Here's a picture that hopefully explains this better:
102+
103+
![Iterables and iterators.](../images/iters.png)
104+
105+
## Iterating manually
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
109+
iterator gets the next value and moves it forward. Like this:
110+
111+
```py
112+
>>> e = enumerate('abc')
113+
>>> e.__next__()
114+
(0, 'a')
115+
>>> e.__next__()
116+
(1, 'b')
117+
>>> e.__next__()
118+
(2, 'c')
119+
>>>
120+
```
121+
122+
There's also a built-in `next()` function that does the same thing:
123+
124+
```py
125+
>>> e = enumerate('abc')
126+
>>> next(e)
127+
(0, 'a')
128+
>>> next(e)
129+
(1, 'b')
130+
>>> next(e)
131+
(2, 'c')
132+
>>>
133+
```
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
137+
to give us, calling `next(e)` raises a StopIteration:
138+
139+
```py
140+
>>> next(e)
141+
Traceback (most recent call last):
142+
File "<stdin>", line 1, in <module>
143+
StopIteration
144+
>>>
145+
```
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
149+
StopIteration.
150+
151+
This is actually what for looping over an iterator does. For example,
152+
this code...
153+
154+
```py
155+
for pair in enumerate('hello'):
156+
print(pair)
157+
```
158+
159+
...does roughly the same thing as this code:
160+
161+
```py
162+
e = enumerate('hello')
163+
while True:
164+
try:
165+
pair = next(e)
166+
except StopIteration:
167+
# it's at the end, time to stop
168+
break
169+
# we got a pair
170+
print(pair)
171+
```
172+
173+
The for loop version is much simpler to write and I wrote the while loop
174+
version just to explain what the for loop does.
175+
176+
## Converting to iterators
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
180+
call `next()` on them:
181+
182+
```py
183+
>>> next('abc')
184+
Traceback (most recent call last):
185+
File "<stdin>", line 1, in <module>
186+
TypeError: 'str' object is not an iterator
187+
>>>
188+
```
189+
190+
There's a built-in function called `iter()` that converts anything
191+
iterable to an iterator.
192+
193+
```py
194+
>>> i = iter('abc')
195+
>>> i
196+
<str_iterator object at 0x7f987b860160>
197+
>>> next(i)
198+
'a'
199+
>>> next(i)
200+
'b'
201+
>>> next(i)
202+
'c'
203+
>>> next(i)
204+
Traceback (most recent call last):
205+
File "<stdin>", line 1, in <module>
206+
StopIteration
207+
>>>
208+
```
209+
210+
Calling `iter()` on anything non-iterable gives us an error.
211+
212+
```py
213+
>>> iter(123)
214+
Traceback (most recent call last):
215+
File "<stdin>", line 1, in <module>
216+
TypeError: 'int' object is not iterable
217+
>>>
218+
```
219+
220+
If we try to convert an iterator to an iterator using `iter()` we just
221+
get back the same iterator.
222+
223+
```py
224+
>>> e = enumerate('abc')
225+
>>> iter(e) is e
226+
True
227+
>>>
228+
```
229+
230+
So code like this...
231+
232+
```py
233+
for thing in stuff:
234+
print(thing)
235+
```
236+
237+
...works roughly like this:
238+
239+
```py
240+
iterator = iter(stuff)
241+
while True:
242+
try:
243+
thing = next(iterator)
244+
except StopIteration:
245+
break
246+
print(thing)
247+
```
248+
249+
## Custom iterables
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
253+
that returns the iterator itself. For example, here's an iterator that
254+
behaves like `iter([1, 2, 3])`:
255+
256+
257+
258+
***
259+
260+
You may use this tutorial freely at your own risk. See
261+
[LICENSE](../LICENSE).
262+
263+
[Previous](../basics/classes.md) | [Next](../README.md) |
264+
[List of contents](../README.md#advanced)

answers.md renamed to basics/answers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,6 @@ isn't exactly like mine but it works just fine it's ok, and you can
436436
***
437437

438438
You may use this tutorial freely at your own risk. See
439-
[LICENSE](LICENSE).
439+
[LICENSE](../LICENSE).
440440

441-
[List of contents](README.md#list-of-contents)
441+
[List of contents](../README.md#list-of-contents)

0 commit comments

Comments
 (0)