Вы находитесь на странице: 1из 496

32.973.2-018.

1
004.43
54


54 Python. , , -
. .: , 2017. 496 .: . ( ).
ISBN 978-5-496-02305-4
Python ,
(, , -
). ? -
, , , ,
.
, :
,
, , , - Django,
. ,
, . !

12+ ( 29 2010 . 436-.)


32.973.2-018.1
004.43

No Starch Press .

.

ISBN 978-1593276034 . 2016 by Eric Matthes


ISBN 978-5-496-02305-4 , 2017
,
, 2017
, 2017

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

I. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2. . . . . . . . . . . . . . . . . . . 32
hello_world.py . . . . . . . . . . . . . . . . . . . . . . . . . . 32
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
0, 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
. . . . . . . . . . . . . . . . . . . . . 59
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5. if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
7. while . . . . . . . . . . . . . . . . . . . . . . . . . 120
input() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
while . . . . . . . . . . . . . . . . . 130
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
. . . . . . . . . . . . . . . . . . . . . 179
Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
7

10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

II. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Python . . . . . . . . . . . . . . . . . . . . . . . . . . 224
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
: game_functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

13. , ! . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
. . . . . . . . . . . . . . . . . . . . . . . . . . . 280
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Play . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
8

15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
Pygal . . . . . . . . . . . . . . . . . . . . . . . . . . 327
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
16. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
CSV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
17. API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
API - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
18. Django . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
19. . . . . . . . . . . . . . . . . . . . . . 408
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
. . . . . . . . . . . . . . . . . . . . . . . . . 419
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
20. . . . . . . . . . . 437
Learning Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
Learning Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
. Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
Python Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
Python OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
Python Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
Python . . . . . . . . . . . . . . . . . . . . . 469
. . . . . . . . . . . . . . . . . . . . . . . . . 471
Geany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
Sublime Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
IDLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
Emacs vim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
9

. . . . . . . . . . . . . . . . . . . . . . . . . 478
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
IRC (Internet Relay Chat) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
. Git . . . . . . . . . . . . . . . . . . . . . . . . 483
Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492

(Eric Matthes), ,
Python . , -
,
-
.
.


(Kenneth Love) Python
. , -
, Python Django,
. -
django-braces,
(mixins) Django.
(@kennethlove).
,
,
, ,

.

, -
No Starch Press. (Bill
Pollock) ,
. (Tyler Ortman) -
. (Liz Chadwick)
(Leslie Shen)
, (Anne Marie Walker)
. (Riley Hoffman) ,
,
.
(Kenneth Love),
. PyCon, -
Python
.
; , -
Python -
.
.
,
, . -

, .

, -
. ,
Digital Equipment Corporation,
. ,
. -
( ), -
, -
. , -
:
! : 25
! : 50
! : 42
! ? (/)
!

, ,
, .
. -
, ; ,
. , ,
, , -
, .

?
,
Python (,
-), -
, .
, -
Python .
,
, -
.
, ,
.
14

?
-
Python . ,
,
. -
, Python,
.
,
Python.
,
. -
.
. , while
if ,
,
.
,
, , -
. ,
,
, , . -
,

. , -
.
. -
, :
,
, . I
.
II , I, -
. ,
. ( 1214) -
Space Invaders, -
. ,
2D-.
( 1517) .
, -
.
, ; , -
; ,
.
,
.
15

( 1820) -
Learning Log. , -
. -
,
. , ,
.

Python?
, Python
, .
Python . Python
: , , -
. Python .
,
.
Python : , -
, -
. Python
.
, Python
Python,
. , -
.
, ,
, . , -
, Python
, Python -
.
Python , !


, ,
comp@piter.com ( , ).
!
- http://www.piter.com
.
I.

I ,
Python. -
, .
1 Python ,
Hello world!. 2 -
, .
3 4 .
, .
,
.
5 if. ,
- , , - ,
.
6 , Python, -
. , , ,
.
7 ,
. while,
, .
8 , -
, .
9 , -
: , , , , ..
, .
10 ,
. , -
. -
Python;
.
11 . ,
, . ,
.
, .
1

Python, hello_world.
py. , Python ,
.
Python. Python -
,
.


Python ,
.
Python, , -
Python .

Python 2 Python 3
Python: Python 2 Python 3. -
,
Python ,
. -
, , Python 2,
Python 3.
Python 2 Python3,
.
Python,
Python 3. Python 2
, -
, Python 2. Python 3,
.

Python
Python ,
Python
.
18 1

:
>>> print("Hello Python interpreter!")
Hello Python interpreter!

,
Enter. -
, ,
.

Python . ,
, ,
.
.

Hello World!
-
, Hello world! ,
.
Python Hello World :
print("Hello world!")

.
, ,
Python, . ,
, .

Python
Python - ; -
, .
Python, ,
Python. ,
Python .
, Python
Hello World . ,
Python , . -
Python hello_world.
py. , Hello World .
,
Python.

Python Linux
Linux ,
Python Linux. ,
19

Linux, , - -
, .
-
, .

Python
, Terminal
(Ubuntu Ctrl+Alt+T). , -
Python , python ( p).
, Python ,
>>>, Python:
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

, Python 2.7.6 Python


, . Ctrl+D -
exit(), Python
.
Python 3, , ;
, ,
Python 2.7, python3:
$ python3
Python 3.5.0 (default, Sep 17 2015, 13:05:18)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

, Python 3,
. , -
python , python3. -
Linux Python , , -
Python 2,
Python 3, .


Geany ; , -
(
) ,
.
, Geany,
.
Linux Geany :
$ sudo apt-get install geany
20 1

, http://geany.org/
Download/ThirdPartyPackages/.

Hello World
, Geany.
Super ( Windows) Geany
. , .
python_work. (
-
, Python.)
Geany Python (FileSave As)
hello_world.py python_work. .py Geany, -
Python. Geany,
.
, :
print("Hello Python world!")

Python, , -
Geany . BuildSet Build
Commands. Compile Execute,
. Geany ,
python, , python3,
.
python3 , Compile
Execute , Geany Python 3.
Compile :
python3 -m py_compile "%f"

. -
.
Execute :
python3 "%f"

. .1.1 ,
Geany.
hello_world.py: BuildExecute,
Execute ( ) F5.
:
Hello Python world!
------------------
(program exited with code: 0)
Press return to continue

, .
, print ?
21

. 1.1. Geany Python 3 Linux

? -
, .
,
. 28.

Python
Python -
python python3, .
, :
>>> print("Hello Python interpreter!")
Hello Python interpreter!
>>>

. , -
Python Ctrl+D exit().

Python OS X
OS X Python .
, Python , -
, .
22 1

Python
( ApplicationsUtilitiesTerminal).
Command+, terminal Enter. -
, Python , python
( p). ,
Python , >>>,
Python:
$ python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits", or "license" for more
information.
>>>

, Python 2.7.5 Python


, . Ctrl+D -
exit(), Python
.
Python 3, python3. -
, , ,
Python 3 , -
. python3 , ,
python ,
python3. - Python
Python 2, Python 3,
.

Python
Python -
python python3, .
, :
>>> print("Hello Python interpreter!")
Hello Python interpreter!
>>>

. , -
Python Ctrl+D exit().


Sublime Text ;
OS X,
( ) , -
, Sublime Text. -
,
Sublime Text, .
23

Sublime Text http://sublimetext.


com/3. OS X.
Sublime Text : -
, -
,
. ,
Sublime Text Applications.

Sublime Text Python 3


Python python
, Sublime Text, ,
Python . -
Python, :
$ type -a python3
python3 is /usr/local/bin/python3

Sublime Text ToolsBuild SystemNew Build


System. .
:
{
"cmd": ["/usr/local/bin/python3", "-u", "$file"],
}

Sublime Text python3 -


. ,
, type -a python3
. Python3.sublime-build
, Sublime Text Save.

Hello World
, Sublime Text
Applications Sublime Text.
Command+ sublime text .
python_work. (
,
Python.)
Python (FileSave As) hello_world.py python_work. -
.py Sublime Text, Python.
Sublime Text, -
.
, :
print("Hello Python world!")

python ,
ToolsBuild Ctrl+B.
24 1

Sublime Text python,


ToolsBuild System, Python 3. Python 3 -
Python ,
ToolsBuild Command+B.
Sublime Text
:
Hello Python world!
[Finished in 0.1s]

, .
, print ?
? -
, .
,
. 28.

Python Windows
Windows Python. ,
Python, .

Python
, Python .
: command
Shift Open command
window here. python .

. 1.2. Add Python to PATH


25

>>>, , -
Python. ,
, , python .
Python Windows.
http://python.org/downloads/. :
Python 3 Python 2. Python 3,
. -
, . -
Add Python to PATH
. .1.2 .


, -
Python .
python .
Python (>>>), , Windows Python:
C:\> python
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 22:15:05) [MSC
v.1900 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
>>>

, Python -
.
:
C:\> python
'python' is not recognized as an internal or external command,
operable
program or batch file.

Windows,
Python. python C;
Windows C. ,
Python, python ( ). -
, Python35,
python, python
C:\Python35\python. , python
Windows ,
python .
, , : -
.
:
C:\> C:\Python35\python
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 22:15:05) [MSC
26 1

v.1900 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
>>>

, , Python -
.

Python
,
Hello Python world!:
>>> print("Hello Python world!")
Hello Python interpreter!
>>>

, Python,
Python. -
, Ctrl+Z exit().


Geany ; , -
(
) ,
.
, Geany,
.
Geany Windows
http://geany.org/. Releases Download
geany-1.25_setup.exe ( - ). -
.
, Geany:
Windows Geany . ,
. -
python_work. (
, -
Python.) Geany Python
(FileSave As) hello_world.py python_work. .py
Geany, Python. Geany,
.
, :
print("Hello Python world!")

python , -
Geany ;
Hello World .28. Python
27

C:\Python35\python,
Geany , .

Geany
Geany Python, BuildSet Build
Commands. Compile Execute,
. Compile Execute python,
, Geany ,
python. ,
.
Compile Execute ,
. Compile :
C:\Python35\python -m py_compile "%f"

, ;
.

. 1.3. Geany Python 3 Windows

Execute :
C:\Python35\python "%f"
28 1

. .1.3 ,
Geany.
, OK.

Hello World
. -
hello_world.py: BuildExecute,
Execute ( ) F5. -
:
Hello Python world!
------------------
(program exited with code: 0)
Press return to continue

, .
, print ?
? -
, .
, ,
.


, -
. hello_world.py, ,
.
, Python -
. Python
. , ,
.
, . , -
: ,
-
. ,
, , .
. , ,
hello_world.py .
- , ,
( ) . .
, - , .
, Python, .
, .
, ,
https://www.nostarch.com/pythoncrashcourse/. -
, .
Python 29

.
(, ..), ,
.
.
- ; -
. ,
, ,
, - . , Python
.
Python ,
.
, .
hello_world.py , Python,
.

Python
, , -
.
, ,
.
Python; -
, . -
, hello_world.py
python_work .

Linux OS X
Python Linux OS X -
. cd (Change Directory) -
. ls (LiSt)
- .
hello_world.py:
~$ cd Desktop/python_work/
~/Desktop/python_work$ ls
hello_world.py
~/Desktop/python_work$ python hello_world.py
Hello Python world!

cd python_work ,
Desktop . ls , hello_world.py -
. python
hello_world.py .
, . python (
python3) Python.
30 1

Windows
cd (Change Directory) -
. dir (DIRectory)
.

hello_world.py:
C:\> cd Desktop\python_work
C:\Desktop\python_work> dir
hello_world.py
C:\Desktop\python_work> python hello_world.py
Hello Python world!

cd python_work,
Desktop . dir , hello_world.py -
. python hello_world.py .

python, , :
C:\$ cd Desktop\python_work
C:\Desktop\python_work$ dir
hello_world.py
C:\Desktop\python_work$ C:\Python35\python hello_world.py
Hello Python world!

.
, , -
.


.
2,
.
1-1. Python.org: Python (http://python.org/) ,
. Python,
.
1-2. Hello World: hello_world.py.
- .
, ? ? -
, ? ,
?
1-3. : -
, ? .
,
; ,
. ,
, .
, .
31

Python Python
, .
, Python. -
Python
hello_world.py. , - -
.
,
Python. , -
Python.
2

,
Python.
.

hello_world.py
, Python
hello_world.py. , Python -
:
hello_world.py
print("Hello Python world!")

:
Hello Python world!

.py hello_world.py , -
Python. Python,
, . ,
print, ,
.
-
. , , print ,
. , Hello Python world!
Python, . ,
, ,
.

hello_world.py.
:
message = "Hello Python world!"
print(message)
33

, . -
:
Hello Python world!

message .
, , . -
Hello Python world!.
Python. -
Hello Python world!
message. ,
, message.
hello_world.py,
. hello_world.py ,
:
message = "Hello Python world!"
print(message)

message = "Hello Python Crash Course world!"


print(message)

hello_world.py :
Hello Python world!
Hello Python Crash Course world!

;
Python .


Python
. ;
. -
, .
, -
. , -
. , message_1, 1_message.
,
. , greeting_
message , greeting message .
Python
; , ,
Python , print (.
Python, . <469>).
, . -
, name n, student_name s_n, name_length
length_of_persons_name.
34 2

l O,
1 0.
, ,
. -
, ,
.

, . -
, .

,
. , ,
. ,
, , .
. -
( mesage
):
message = "Hello Python Crash Course reader!"
print(mesage)

, Python -
. ,
,
.
, Python
:
Traceback (most recent call last):
File "hello_world.py", line 2, in <module>
print(mesage)
NameError: name 'mesage' is not defined

, 2 hello_world.py. -
, , -
.
: (mesage) . -
, Python .
,
.
, -
s. Python , ,
35

. , ,
message :
mesage = "Hello Python Crash Course reader!"
print(mesage)

!
Hello Python Crash Course reader!

, .
, ,
.
-
.
, , . -
.

.

?
. , -
- . ,
. , .


. -
,
Python , simple_
message.py simple_messages.py.
2-1. :
.
2-2. : .
.

,
- , .
. ,
.
. -
, , Python ;
, :
"This is a string."
'This is also a string.'
36 2

:
'I told my friend, "Python is my favorite language!"'
"The language 'Python' is named after Monty Python, not the snake."
"One of Python's strengths is its diverse and supportive community."


, ,
. ,
:
name.py
name = "ada lovelace"
print(name.title())

name.py . -
:
Ada Lovelace

name ,
"ada lovelace". print()
title(). , Python
. (.) name name.title() Python
title() name.
,
. .
title() ,
.
title()
, . -
, ,
Ada, ADA ada ,
Ada.
. ,
:
name = "Ada Lovelace"
print(name.upper())
print(name.lower())

:
ADA LOVELACE
ada lovelace

lower() .
, -
37

,
. , , ,
.

. ,

:
first_name = "ada"
last_name = "lovelace"
full_name = first_name + " " + last_name

print(full_name)

Python ( + ). -
first_name ,
last_name :
ada lovelace

. -
, -
. :
first_name = "ada"
last_name = "lovelace"
full_name = first_name + " " + last_name

print("Hello, " + full_name.title() + "!")

,
title() .
, :
Hello, Ada Lovelace!

,
:
first_name = "ada"
last_name = "lovelace"
full_name = first_name + " " + last_name

message = "Hello, " + full_name.title() + "!"


print(message)

Hello, Ada Lovelace!, -



.
38 2


(whitespace) -
, , .
, .

\t, :
>>> print("Python")
Python
>>> print("\tPython")
Python

\n:
>>> print("Languages:\nPython\nC\nJavaScript")
Languages:
Python
C
JavaScript

. , -
"\n\t" Python ,
.

:
>>> print("Languages:\n\tPython\n\tC\n\tJavaScript")
Languages:
Python
C
JavaScript

,
.


. -
'python' 'python ' ,
. Python 'python ' , -
, .
,
, . -
.
. , Python
, .
Python .
, ( ) ,
rstrip().
39

>>> favorite_language = 'python '


>>> favorite_language
'python '
>>> favorite_language.rstrip()
'python'
>>> favorite_language
'python '

, favorite_language , -
. Python -
, .
rstrip() favorite_language ,
. , :
favorite_language , , ,
.
,
:
>>> favorite_language = 'python '
>>> favorite_language = favorite_language.rstrip()
>>> favorite_language
'python'

, -
.
.

.
( ) -
lstrip(), strip() :
>>> favorite_language = ' python '
>>> favorite_language.rstrip()
' python'
>>> favorite_language.lstrip()
'python '
>>> favorite_language.strip()
'python'

.
, .
, -
.
.


.
, Python
Python. ,
40 2

, . - , Python

. Python
Python, .
, . -
apostrophe.py :
apostrophe.py
message = "One of Python's strengths is its diverse community."
print(message)

, , -
Python
:
One of Python's strengths is its diverse community.

Python ,
:
message = 'One of Python's strengths is its diverse community.'
print(message)

:
File "apostrophe.py", line 1
message = 'One of Python's strengths is its diverse community.'
^
SyntaxError: invalid syntax

,
. , -
- Python.
;
, .
, -
Python. ,
, -
. - ,
.


. , Python
( Python), , - -
.

Python 2
Python 2 print :
41

>>> python2.7
>>> print "Hello Python 2.7 world!"
Hello Python 2.7 world!

Python 2 . -
Python 3 print , .
print Python 2 , -
, Python3.
, Python 2, print
, .


name_
cases.py. , -
.
2-3. : ,
. , :
Hello Eric, would you like to learn some Python today?
2-4. :
, .
2-5. : , . -
. (
):
Albert Einstein once said, "A person who never made a

mistake never tried anything new."


2-6. 2: 2-5,
famous_person.
message. .
2-7. : .
. , -
, \t \n, .
, .
: lstrip(), rstrip() strip().

,
, -
.. Python
. , Python ,
.


Python (+), -
(-), (*) (/).
42 2

>>> 2 + 3
5
>>> 3 - 2
1
>>> 2 * 3
6
>>> 3 / 2
1.5

Python . -
Python
:
>>> 3 ** 2
9
>>> 3 ** 3
27
>>> 10 ** 6
1000000

Python , -
.
,
. :
>>> 2 + 3*4
14
>>> (2 + 3) * 4
20

, Python ;
.


Python , , ( -
).
, .
, Python , :
>>> 0.1 + 0.1
0.2
>>> 0.2 + 0.2
0.4
>>> 2 * 0.1
0.2
>>> 2 * 0.2
0.4

, -
:
>>> 0.2 + 0.1
0.30000000000000004
43

>>> 3 * 0.1
0.30000000000000004

; .
Python ,
- -
. ; ,
,
II.

str()
. ,
.
:
birthday.py
age = 23
message = "Happy " + age + "rd Birthday!"
print(message)

, : Happy 23rd birthday!


, , :
Traceback (most recent call last):
File "birthday.py", line 2, in <module>
message = "Happy " + age + "rd Birthday!"
TypeError: Can't convert 'int' object to str implicitly
. , Python ,
. Python , -
(int), ,
. ,
23, 2 3.
,
. str(), -
- :
age = 23
message = "Happy " + str(age) + "rd Birthday!"

print(message)

Python , 23
2 3 .
:
Happy 23rd Birthday!
Python -
. , , Python
.
44 2

Python 2
Python 2 :
>>> python2.7
>>> 3 / 2
1

1.5 Python 1. Python 2


. :
, .
Python 2, ,
.
:
>>> 3 / 2
1
>>> 3.0 / 2
1.5
>>> 3 / 2.0
1.5
>>> 3.0 / 2.0
1.5

, , -
Python 3, Python 2, .
,
, .


2-8. 8: , , ,
8. print, -
. , :
print(5 + 3)
,
8.
2-9. : . -
. .

.
Python.
,
, , -
.

?
Python (#). -
Python , #
. :
Python 45

comment.py
# Say hello to everyone.
print("Hello Python people!")

Python .
Hello Python people!

?
, ,
. ,
. , ,
, . ,
, , -
.
-
,
.
, -
, . -
,
. ,
,
.
, , ,

; , -
. ,
. -
.


2-10. :
. , ,
,
. , .

Python
Perl -
.
Perl. Perl -
: . -
, , ,
. -
46 2

, ,
.
, ,
.
Python -
, . Python
The Zen of Python.
Python,
import this . ,
, ,
Python.
>>> import this
The Zen of Python, by Tim Peters

, .
Python , .
.
, .
Python, , -
: ,
!
, .
, -
. , -
.
, .
; .
, .
.
, . ,
,
.

.
Python ,
. ,
. ! -
,
, .
Python.
, .
Python
, .
47

; , ,
, -
.

, .
,
.


2-11. Python: import this Python -
.

. ,
-
. ,
/ . -
,
.
, -
.
,
.
.
3 ,
. ,
.
3

,
.
,
.
Python, .
-
.

?
, .
, 0 9
. ,
- . -
,
: letters, digits, names ..
Python ( []),
.
:
bicycles.py
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)

Python ,
:
['trek', 'cannondale', 'redline', 'specialized']

, ; ,
.


, -
Python ()
0, 1 49

. , ,
.
, bicycles
:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])

.
, Python
:
trek
, -
.
2
. , 'trek'
title():
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0].title())

, , 'Trek'
.

0, 1
Python , 0, 1.

. -
, ,
1.
1.
1 . -
, ,
3.
1 3:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[1])
print(bicycles[3])

:
cannondale
specialized

Python
. 1, Python
:
50 3

bicycles = ['trek', 'cannondale', 'redline', 'specialized']


print(bicycles[-1])

'specialized'. ,
,
.
. 2 -
, 3 ..


, -
. ,
, .
,
.
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
message = "My first bicycle was a " + bicycles[0].title() + "."

print(message)

, bicycles[0],
message. -
:
My first bicycle was a Trek.


,
Python. ,
, .
3-1. : names.
, ( ).
3-2. : , 3-1,
.
, .
3-3. : (,
) . -
: Honda.

,
; , -

. , ,
.
; , , .
0, 1 51

, , .
.



. , -
; ,
.
, ,
'honda'. ?
motorcycles.py

motorcycles = ['honda', 'yamaha', 'suzuki']


print(motorcycles)

motorcycles[0] = 'ducati'
print(motorcycles)

,
'honda'. 'ducati'.
, , -
:
['honda', 'yamaha', 'suzuki']
['ducati', 'yamaha', 'suzuki']

,
.


,
,
-
. Python
.


-
. ,
'ducati':
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)

motorcycles.append('ducati')
print(motorcycles)
52 3

append() 'ducati' ,
:
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha', 'suzuki', 'ducati']

append() . , -
append().
'honda', 'yamaha'
'suzuki':
motorcycles = []

motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')

print(motorcycles)

, :
['honda', 'yamaha', 'suzuki']

, ,
, -
.
, ,
.


insert() -
. .
motorcycles = ['honda', 'yamaha', 'suzuki']

motorcycles.insert(0, 'ducati')
print(motorcycles)

'ducati' . -
insert() 0
'ducati'.
:
['ducati', 'honda', 'yamaha', 'suzuki']



. , ,
.
-,
0, 1 53

. -
.

del
, , -
del.
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)

del motorcycles[0]
print(motorcycles)

del , 'honda', motorcycles:


['honda', 'yamaha', 'suzuki']
['yamaha', 'suzuki']

del , -
. , 'yamaha':
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)

del motorcycles[1]
print(motorcycles)

:
['honda', 'yamaha', 'suzuki']
['honda', 'suzuki']

,
del, .

pop()
, , - . ,
x y , -
. - ,
, ..
pop() ,
. :
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)

popped_motorcycle = motorcycles.pop()
print(motorcycles)
print(popped_motorcycle)

motorcycles.

54 3

popped_motorcycle. , -
. ,
, .
, 'suzuki', ,
popped_motorcycle:
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha']
suzuki

pop()? ,
.
pop()
:
motorcycles = ['honda', 'yamaha', 'suzuki']

last_owned = motorcycles.pop()
print("The last motorcycle I owned was a " + last_owned.title() + ".")

:
The last motorcycle I owned was a Suzuki.


pop()
; .
motorcycles = ['honda', 'yamaha', 'suzuki']

first_owned = motorcycles.pop(0)
print('The first motorcycle I owned was a ' + first_owned.title() +
'.')

, -
.
:
The first motorcycle I owned was a Honda.

, pop() , ,
.
, del -
pop(), .
, , del;
,
pop().

.
, remove().
0, 1 55

, 'ducati':
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)

motorcycles.remove('ducati')
print(motorcycles)

Python ,
'ducati', :
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']

remove() ,
. 'ducati'
:
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
too_expensive = 'ducati'
motorcycles.remove(too_expensive)
print(motorcycles)
print("\nA " + too_expensive.title() + " is too expensive for me.")

'ducati' -
too_expensive . Python,
. 'ducati'
, too_expensive,
'ducati' -
:
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']

A Ducati is too expensive for me.

remove() . -
, , -
, . , ,
7.


2,
.
3-4. : ( )
, ? , ,
.
.
56 3

3-5. : , ,
. -
- .
3-4. print
, .
, ,
.
-
, .
3-6. : .
.
3-4 3-5. -
print, .
insert() .
insert() .
append() .
-
, .
3-7. : , -
, .
3-6.
, .
pop()
, . ,
, , -
.
, .
, .
del ,
. , ,
.


, -
.
,
.
,

. Python
.

sort()
sort() . ,
, .
57

, , -
.
cars.py
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)

sort()
. , -
:
['audi', 'bmw', 'subaru', 'toyota']

;
sort() reverse=True.
, :
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)
print(cars)

:
['toyota', 'subaru', 'bmw', 'audi']

sorted()
,
, sorted().
sorted() ,
.
.
cars = ['bmw', 'audi', 'toyota', 'subaru']

print("Here is the original list:")


print(cars)

print("\nHere is the sorted list:")


print(sorted(cars))

print("\nHere is the original list again:")


print(cars)

, .
, , ,
.
Here is the original list:
['bmw', 'audi', 'toyota', 'subaru']

Here is the sorted list:


58 3

['audi', 'bmw', 'subaru', 'toyota']

Here is the original list again:


['bmw', 'audi', 'toyota', 'subaru']

: sorted() -
. sorted()
reverse=True, , .

, -
. -
, ( ,
). , ,
.


,
reverse(). , -
, -
:
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)

cars.reverse()
print(cars)

: reverse() -
, :
['bmw', 'audi', 'toyota', 'subaru']
['subaru', 'toyota', 'audi', 'bmw']

reverse() ,
, reverse() -
.


len().
, 4:
>>> cars = ['bmw', 'audi', 'toyota', 'subaru']
>>> len(cars)
4

len() , -
; ,
; - ..
59

Python , 1, -
1 .


3-8. : , .
. ,
.
. ,
Python.
sorted() -
.
, , -
.
sorted()
.
, , .
reverse(). , ,
.
reverse(). ,
, .
sort(). ,
, .
sort() .
, , .
3-9. : 3-4 3-7 len()
, .
3-10. : , .
, , , , , , . -
, , ,
, .



,
. , ,
:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles[3])

:
Traceback (most recent call last):
File "motorcycles.py", line 3, in <module>
print(motorcycles[3])
IndexError: list index out of range
60 3

Python 3.
motorcycles 3. -
1 . ,
3, 1.
Python 2,
0.
, Python , -
. -
, 1.
.
,
1. ,
:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles[-1])

1 ,
'suzuki':
'suzuki'


:
motorcycles = []
print(motorcycles[-1])

motorcycles , Python
:
Traceback (most recent call last):
File "motorcyles.py", line 3, in <module>
print(motorcycles[-1])
IndexError: list index out of range

, ,
. , ,
, . -

.


3-11. : -
, .
, .
, .
61

, -
. ,
, ( ).
, -
.
4 . -
, -
, .
4

3 -
. , -
( ).
.
, -
.



. , -
,
-
. ,
. ,
, for.
, ,
. , ,
. -,
. -,
. for :
Python -
.
for :
magicians.py

magicians = ['alice', 'david', 'carolina']


for magician in magicians:
print(magician)

, 3.
for. Python -
magician. , -
magician.
63

. :
. :
alice
david
carolina


,
. ,
, magicians.py, Python :
for magician in magicians:

, magicians -
magician. 'alice'.
Python :
print(magician)

Python magician, 'alice'.


, Python
:
for magician in magicians:

Python 'david' magician.


:
print(magician)

Python magician; 'david'.


, 'carolina'.
, Python -
. for ,
.
,
. ,
Python .
, for
. -
,
. :
for cat in cats:
for dog in dogs:
for item in list_of_items:

, -
for. , -
64 4

, ,
.

for
for
. ,
:
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")

,
.
magician 'alice', Python
'Alice'. -
'David', 'Carolina':
Alice, that was a great trick!
David, that was a great trick!
Carolina, that was a great trick!

for . -
for magician in magicians
. -
,
.
:
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.
title() + ".\n")

print ,
. ("\n")
print -
. ,
:
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

David, that was a great trick!


I can't wait to see your next trick, David.

Carolina, that was a great trick!


I can't wait to see your next trick, Carolina.
65

for .
for -
.

for
for?
.
for, , -
. ,
. -
, for :
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n")

print("Thank you, everyone. That was a great magic show!")

print
, . ,
:
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

David, that was a great trick!


I can't wait to see your next trick, David.

Carolina, that was a great trick!


I can't wait to see your next trick, Carolina.

Thank you, everyone. That was a great magic show!

for
, . , for
, -
. ,
, .


Python -
. ,
, , . -
Python .

. Python
66 4

.
.
,
,
. , ,
, , .
-
, .
, .


for .
, Python :
magicians.py
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)

print , . Python -
, ,
:
File "magicians.py", line 3
print(magician)
^
IndentationError: expected an indented block

( ), for.


, .
, ,
.
, ,
:
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() +
".\n")

print , , Python
for,
. print
67

, . print
, .
magician 'carolina', -
:
Alice, that was a great trick!
David, that was a great trick!
Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

. ,
, .
,
, ,
.


, , Python -
:
hello_world.py
message = "Hello Python world!"
print(message)

print ,
; Python :
File "hello_world.py", line 2
print(message)
^
IndentationError: unexpected indent

, ,
. ,
Python, ,
for.


, -
, . Python
,
.
, ,
?
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")
68 4

print("I can't wait to see your next trick, " + magician.title() + ".\n")

print("Thank you everyone, that was a great magic show!")

,
:
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

Thank you everyone, that was a great magic show!


David, that was a great trick!
I can't wait to see your next trick, David.

Thank you everyone, that was a great magic show!


Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

Thank you everyone, that was a great magic show!

, -
. 66. Python ,
, ,
. , ,
, , .


for Python,
.
magicians = ['alice', 'david', 'carolina']
for magician in magicians
print(magician)

, ,
, .
, .
, -
. ,
, .


4-1. : . -
for .
for , -
, . , -
I like pepperoni pizza.
( for) .
, ( )
, , I really love pizza!.
69

4-2. : ( ) , -
. for .
, ,
, A dog would make a great pet.
. ,
Any of these animals would make a great pet!.


-
. ,
, ..
: , ,
, / .
, Python
.
, ,
, .

range()
range() . ,
:
numbers.py
for value in range(1,5):
print(value)

, 1 5,
5 :
1
2
3
4

range() 1 4. -
1, .
range() Python -
. -
, (5 ) .
1 5, range(1,6):
for value in range(1,6):
print(value)

1 5:
70 4

1
2
3
4
5

range() ,
, 1.

range()
, range() -
list(). range() list(), -
.
-
. list():
numbers = list(range(1,6))
print(numbers)

:
[1, 2, 3, 4, 5]

range() , -
. ,
1 10 :
even_numbers.py
even_numbers = list(range(2,11,2))
print(even_numbers)

range() 2, -
2. 2 ,
11,
:
[2, 4, 6, 8, 10]

range() .
, 1 10? -
Python (**).
:
squares.py

squares = []
for value in range(1,11):
square = value**2
squares.append(square)
print(squares)
71

squares. -
Python 1 10 range().
,
square . square -
squares. ,
:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

,
square :
squares = []
for value in range(1,11):
squares.append(value**2)

print(squares)

, squares.py.
, -
.
-
. ;
. -
, ,
,
.


Python .
, , :
>>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> min(digits)
0
>>> max(digits)
9
>>> sum(digits)
45

, , -
. ,
.


squares
. (list comprehension) -
72 4

. for

. -
, ,
,
.
, ,
:
squares.py
squares = [value**2 for value in range(1,11)]
print(squares)

, ,
squares.
, . -
value**2, .
for , -
, . for for value
in range(1,11) 1 10 value**2.
for.
:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

,
. , ,
. -
, .


4-3. 20: for 1 20 .
4-4. : 1 1000000, for
. ( ,
Ctrl+C .)
4-5. : 1 1000000, -
min() max() , -
1 1000000. sum() ,
Python .
4-6. : range()
1 20. for.
4-7. : , 3, 3 30.
for.
4-8. : . ,
2 Python 2**3. 10 (
1 10) for.
4-9. :
10 .
73


3 , ,
. -
; Python
(slices).


, ,
. range(), Python
, . ,
, 0 3,
0, 1 2.
:
players.py
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3])

, .
, :
['charles', 'martina', 'michael']

. , -
, , 1
4:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[1:4])

'martina'
'florence':
['martina', 'michael', 'florence']

, Python
:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4])

Python :
['charles', 'martina', 'michael', 'florence']

, . -
, , 2
:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[2:])
74 4

Python :
['michael', 'florence', 'eli']

-
. ,
, ; ,
. ,
, players[-3:]:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[-3:])

,
.


, , -
for.
:
players = ['charles', 'martina', 'michael', 'florence', 'eli']

print("Here are the first three players on my team:")


for player in players[:3]:
print(player.title())

, Python
:
Here are the first three players on my team:
Charles
Martina
Michael

. ,

. -
, ,
. -
. -
,
.



. , , -
, .
75

, ,
([:] ). ,
;
.
,
, .
,
:

foods.py
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]

print("My favorite foods are:")


print(my_foods)

print("\nMy friend's favorite foods are:")


print(friend_foods)

my_foods. -
friend_foods. my_foods,
my_foods ,
friend_foods.
, :
My favorite foods are:
['pizza', 'falafel', 'carrot cake']

My friend's favorite foods are:


['pizza', 'falafel', 'carrot cake']

, ,
:
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]

my_foods.append('cannoli')
friend_foods.append('ice cream')

print("My favorite foods are:")


print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)

my_foods friend_foods,
.
: 'cannoli' my_foods, 'ice cream' friend_foods.
, -
.
76 4

My favorite foods are:


['pizza', 'falafel', 'carrot cake', 'cannoli']

My friend's favorite foods are:


['pizza', 'falafel', 'carrot cake', 'ice cream']

, 'cannoli' my_foods,
'ice cream' . , 'ice cream'
friend_foods, 'cannoli' .
, .
, -
:
my_foods = ['pizza', 'falafel', 'carrot cake']

# This doesn't work:


friend_foods = my_foods

my_foods.append('cannoli')
friend_foods.append('ice cream')

print("My favorite foods are:")


print(my_foods)

print("\nMy friend's favorite foods are:")


print(friend_foods)

my_foods friend_foods , -
friend_foods my_foods.
Python, friend_foods ,
my_foods, .
'cannoli' my_foods
friend_foods. 'ice cream'
, friend_foods.
, ,
, :
My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

My friend's favorite foods are:


['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

- , . ,
- , ,
, .


4-10. : , , ,
.
77

The first three items in the list are:,


.
Three items from the middle of the list are:,
.
The last three items in the list are:,
.
4-11. , : 4-1.
, friend_pizzas. .
.
friend_pizzas.
, . My
favorite pizzas are:, for. My
friends favorite pizzas are:, for. ,
.
4-12. : foods.py
for . foods.py
for .

, -
. ,
-
. -
, . (tuples)
. Python ,
, (immutable),
.


, , -
. -
, .
, ,
. , -
:
dimensions.py
dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])

dimensions,
. -
,
:
78 4

200
50
,
dimensions:

dimensions = (200, 50)


dimensions[0] = 250

, Python
. , ,
, Python
:
Traceback (most recent call last):
File "dimensions.py", line 3, in <module>
dimensions[0] = 250
TypeError: 'tuple' object does not support item assignment

, , Python
, .


for,
:
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)

Python ,
:
200
50


,
, . ,
:
dimensions = (200, 50)
print("Original dimensions:")
for dimension in dimensions:
print(dimension)

dimensions = (400, 100)


print("\nModified dimensions:")
for dimension in dimensions:
print(dimension)
79

.
dimensions ,
. Python ,
:
Original dimensions:
200
50

Modified dimensions:
400
100

.
,
.


4-13. : .
.
for , .
, Python
.
, .
, , for
.


, ,
.
, .
, ,
.
Python ,
.
Python, Python,
, .
- , -
,
.


- Python, PEP
(Python Enhancement Proposal). PEP
PEP 8 . PEP 8
80 4

, -
, , .
Python ,
, . , ,
.
. -
, .
, , ,
, Python .
, .

PEP 8 . -
-
.

. -
, Python ,
. -
,
. , , ,
.
, -
. ,
, ,
.


Python 80 -
. - ,
79 .
,
79 -
.
;
, . PEP 8
72 ,
,
, -
.
PEP 8 , -
99 . ,
81

, ,
PEP 8.
( ), -
, .

, ,
-
79 .


. -
,
. , , .
, ,
- ,
.
.
, .
Python
, .


PEP 8 ,
, ,
. Python
PEP 8.


4-14. PEP 8 https://python.org/dev/
peps/pep-0008/. ,
.
4-15. : , ,
PEP 8.
.
,
, ( -
).
80 . ,
80- .
.
82 4

. ,
for, Python -

. , -
. ,

. , -
, ,
(
) .
5 if.
-
, .
if
, .
5 if


. if Python

.

. if,
if .
; , ,
, ,
.


, -
if. ,
, .
( ,
). , 'bmw'
.
'bmw'. , 'bmw',
:
cars.py
cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
if car == 'bmw':
print(car.upper())
else:
print(car.title())

, car 'bmw'.
, -
. car , 'bmw',
:
Audi
BMW
84 5 if

Subaru
Toyota

,
. ,
.


if , -
(True) (False);
. Python ,
if. True, Python
, if.



, . ,
:
>>> car = 'bmw'
>>> car == 'bmw'
True

car 'bmw';
=, . ,
car 'bmw'; (==).
True, ;
, False.
, Python True.
car 'bmw',
False:

>>> car = 'audi'


>>> car == 'bmw'
False

;
car 'audi'. , ,
, : car 'bmw'?
.


Python . ,
:
85

>>> car = 'Audi'


>>> car == 'audi'
False

, .
,
:
>>> car = 'Audi'
>>> car.lower() == 'audi'
True

True 'Audi',
. lower()
, car,
:
>>> car = 'Audi'
>>> car.lower() == 'audi'
True
>>> car
'Audi'

'Audi' car. car


'audi',
. , Python
True. , , car,
.
- , -
. , ,
, (
, ).
- ,
.
'John' , -
'john'.


, ,
(!=). -
, .
if.
;
(anchovies), :
toppings.py
requested_topping = 'mushrooms'

if requested_topping != 'anchovies':
print("Hold the anchovies!")
86 5 if

requested_topping 'anchovies'.
, Python True
if. , Python False
if. requested_topping 'anchovies',
print :
Hold the anchovies!

, -
, ,
.


. ,
, age 18:
>>> age = 18
>>> age == 18
True

. ,
, answer :
magic_ number.py
answer = 17
if answer != 42:
print("That is not the correct answer. Please try again!")

, answer (17) 42.


, :
That is not the correct answer. Please try again!
-
: , , , :
>>> age = 19
>>> age < 21
True
>>> age <= 21
True
>>> age > 21
False
>>> age >= 21
False

if, -
.


. , -
,
87

; ,
. and or .

and
, ,
and; , .
( ) , False.
, , 21 , -
:
>>> age_0 = 22
>>> age_1 = 18
>>> age_0 >= 21 and age_1 >= 21
False
>>> age_1 = 22
>>> age_0 >= 21 and age_1 >= 21
True

, age_0 age_1. -
, 21 . ,
, False.
age_1 22. age_1 21;
, .
, ,
. :
(age_0 >= 21) and (age_1 >= 21)

or
or ,
,
. , -
.
, ,
21:
>>> age_0 = 22
>>> age_1 = 18
>>> age_0 >= 21 or age_1 >= 21
True
>>> age_0 = 18
>>> age_0 >= 21 or age_1 >= 21
False

, . -
age_0 , .
age_0 18.
, .
88 5 if


, , -
. ,
,
, ,
.
, , -
in . , .
, , ,
.
>>> requested_toppings = ['mushrooms', 'onions', 'pineapple']
>>> 'mushrooms' in requested_toppings
True
>>> 'pepperoni' in requested_toppings
False

in Python , -
'mushrooms' 'pepperoni' requested_toppings. ,
, ,
, .


,
. not.
, .
, ,
:
banned_users.py
banned_users = ['andrew', 'carolina', 'david']
user = 'marie'

if user not in banned_users:


print(user.title() + ", you can post a response if you wish.")

:
banned_users, Python True .
'marie' , -
:
Marie, you can post a response if you wish.



.
if 89

. True False,
.

, -
:
game_active = True
can_edit = False

-
,
.


5-1. : .
. :

car = 'subaru'
print("Is car == 'subaru'? I predict True.")
print(car == 'subaru')
print("\nIs car == 'audi'? I predict False.")
print(car == 'audi')

. , ,
True False.
10 . 5 True,
5 False.
5-2. : 10. -
conditional_tests.py.
.
.
lower().
, , ,
, .
and or.
.
.

if
, ,
if. if,
. if
,
.
90 5 if

if
if :
if :

,
. , Python
if, , .
, , .
, :

voting.py
age = 19
if age >= 18:
print("You are old enough to vote!")

Python , age 18.


print :
You are old enough to vote!

if , for. -
, if ,
.
if .
,
:
age = 19
if age >= 18:
print("You are old enough to vote!")
print("Have you registered to vote yet?")

, print ,
:
You are old enough to vote!
Have you registered to vote yet?
age 18, .

if-else
, -
, , . if-else
. if-else if, else
, .
if 91

, ,
,
:
age = 17
if age >= 18:
print("You are old enough to vote!")
print("Have you registered to vote yet?")
else:
print("Sorry, you are too young to vote.")
print("Please register to vote as soon as you turn 18!")

, print.
, else . age
18, , else:
Sorry, you are too young to vote.
Please register to vote as soon as you turn 18!

, : -
, . if -else
, Python
. if-else
.

if-elif-else
;
Python if-elif-else. Python
if-elif-else.
, . ,
, Python .
.
,
:
4 .
4 18 $5.
18 $10.
if ?
, , -
:
amusement_park.py
age = 12

if age < 4:
print("Your admission cost is $0.")
elif age < 18:
print("Your admission cost is $5.")
92 5 if

else:
print("Your admission cost is $10.")

if , 4 .
, , Python
. elif
if, ,
. ,
4 , .
18 , , Python
else. if elif, Python else
.
, -
. (12 18),
. :
Your admission cost is $5.
17 . -
else , $10.
if-elif-else,
, :
if-elif-else, print :
age = 12

if age < 4:
price = 0
elif age < 18:
price = 5
else:
price = 10

print("Your admission cost is $" + str(price) + ".")

, price age,
. if-elif-else
print -
.
, , if-elif-else
. -
, . -
, : .
,
print .

elif
elif. , -
,
if 93

, -
. , 65
, $5:
age = 12

if age < 4:
price = 0
elif age < 18:
price = 5
elif age < 65:
price = 10
else:
price = 5

print("Your admission cost is $" + str(price) + ".")

. elif
, 65 , -
$10. : , else ,
$5,
65 .

else
Python , if-elif else.
else ; -
elif :
age = 12

if age < 4:
price = 0
elif age < 18:
price = 5
elif age < 65:
price = 10
elif age >= 65:
price = 5

print("Your admission cost is $" + str(price) + ".")

elif $5, 65 ;
, else. -

.
else : ,
if elif,
.
, elif
else. ,
.
94 5 if


if-elif-else , , -
. Python
, . -
, .
, .
if elif
else. , -
.
. - ,
:
toppings.py
requested_toppings = ['mushrooms', 'extra cheese']

if 'mushrooms' in requested_toppings:
print("Adding mushrooms.")
if 'pepperoni' in requested_toppings:
print("Adding pepperoni.")
if 'extra cheese' in requested_toppings:
print("Adding extra cheese.")

print("\nFinished making your pizza!")

, .
if , -
, .
if, elif else,
, -
. ,
, . -
.
,
:
Adding mushrooms.
Adding extra cheese.

Finished making your pizza!

if-elif-else, -
, .
:
requested_toppings = ['mushrooms', 'extra cheese']

if 'mushrooms' in requested_toppings:
print("Adding mushrooms.")
elif 'pepperoni' in requested_toppings:
print("Adding pepperoni.")
if 95

elif 'extra cheese' in requested_toppings:


print("Adding extra cheese.")

print("\nFinished making your pizza!")

( 'mushrooms') . -
'extra cheese' 'pepperoni' ,
if-elif-else
.
:
Adding mushrooms.

Finished making your pizza!

, , , -
if-elif-else. ,
if.


5-3. 1: ,
. alien_color green,
yellow red.
if , green.
, ,
5.
, if , -
, . ( -
.)
5-4. 2: , 5-3,
if-else.
if , green.
, ,
5.
, ,
10 .
, if, ,
else.
5-5. 3: if-else 5-4 if-elif-else.
'green, ,
5 .
'yellow, ,
10 .
'red, , -
15 .
, -
.
5-6. : if-elif-else -
. age, .
2 .
96 5 if

2, 4 .
4, 13 .
13, 20 .
20, 65 .
65 .
5-7. : . -
if , .
favorite_fruits.
if. , -
. , if -
You really like bananas!.

if
if . -
, ,
,
,
. if -
, .


, , -
(, 'bmw'),
. ,
if,
.
. , -
.
: , -
, :
toppings.py
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']

for requested_topping in requested_toppings:


print("Adding " + requested_topping + ".")

print("\nFinished making your pizza!")

, for:
Adding mushrooms.
Adding green peppers.
Adding extra cheese.

Finished making your pizza!


if 97

? if for
:
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']

for requested_topping in requested_toppings:


if requested_topping == 'green peppers':
print("Sorry, we are out of green peppers right now.")
else:
print("Adding " + requested_topping + ".")

print("\nFinished making your pizza!")


. , ,
, . else
, .
,
:
Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.

Finished making your pizza!


, , -
: , -
. ,
, ,
.
for ,
.
, ,
. , ,
. ,
, :
requested_toppings = []

if requested_toppings:
for requested_topping in requested_toppings:
print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
else:
print("Are you sure you want a plain pizza?")

.
for,
98 5 if

. if, Python True,


; , -
False. requested_toppings ,
for, .
, , ,
.
, :
Are you sure you want a plain pizza?

,
.


, -
. ?
if , ,
.
,
. .
, , -
. requested_toppings
:
available_toppings = ['mushrooms', 'olives', 'green peppers',
'pepperoni', 'pineapple', 'extra cheese']

requested_toppings = ['mushrooms', 'french fries', 'extra cheese']

for requested_topping in requested_toppings:


if requested_topping in available_toppings:
print("Adding " + requested_topping + ".")
else:
print("Sorry, we don't have " + requested_topping + ".")

print("\nFinished making your pizza!")

. ,
, -
. ,
. 'french fries'.
.
,
. ,
. , else .
else , .
, :
if 99

Adding mushrooms.
Sorry, we don't have french fries.
Adding extra cheese.

Finished making your pizza!


5-8. Hello Admin: ,
admin. , ,
.
.
'admin : Hello
admin, would you like to see a status report?
: Hello Eric,
thank you for logging in again.
5-9. : hello_admin.py if, ,
.
, : We need to find some users!
, -
.
5-10. : -
, .
current_users, .
new_users, .
, current_
users.
new_users ,
. , ,
. ,
.
, .
'John , JOHN .
5-11. : -
th ( 1st, 2nd 3rd).
1 9 .
.
if-elif-else -
. 1st 2nd 3rd
4th 5th 6th 7th 8th 9th,
.

if
. PEP 8
, :
100 5 if

(, ==, >=, <= ..) . -


,
if age < 4:

, :
if age<4:

Python;
.


5-12. if: , ,
, .
5-13. : ,
. , -
, ,
. ,
. , - , -
-?

, -
(True False.)
if, if-else if-elif-else.
, -
, . ,

for.
Python, -
.
6 Python. ,
.
, ,
if.
.
6

,
. , -
, , .
,
. ,
,
.

. , , ,
.
, , , .
, ,
: , ,
..


, -
.
:
alien.py
alien_0 = {'color': 'green', 'points': 5}

print(alien_0['color'])
print(alien_0['points'])

alien_0 : (color) (points).


print
:
green
5

, , -
. , ,
.
102 6


Python .
,
, . , ,
. , ,
Python, .
Python {}, -
, :
alien_0 = {'color': 'green', 'points': 5}

, .
, Python , . -
, .
.
,
alien_0:
alien_0 = {'color': 'green'}

alien_0,
. 'color' ;
'green'.


, , ,
:
alien_0 = {'color': 'green'}
print(alien_0['color'])

, 'color',
alien_0:
green

. ,
alien_0 :
alien_0 = {'color': 'green', 'points': 5}

,
alien_0: color points. ,
:
alien_0 = {'color': 'green', 'points': 5}

new_points = alien_0['points']
print("You just earned " + str(new_points) + " points!")
103

, ,
'points' , .
new_points.
:
You just earned 5 points!
, -
, .


:
. -
, .
alien_0 : x y -
. ,
, 25 .
,
x 0, y 25:
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)

,
. .
: 'x_position' -
0. 'y_position' . -
:
{'color': 'green', 'points': 5}
{'color': 'green', 'points': 5, 'y_position': 25, 'x_position': 0}

.
, .
: .
Python , ;
.


( )
, . -
, , -
( ). ,
alien_0:
104 6

alien_0 = {}

alien_0['color'] = 'green'
alien_0['points'] = 5

print(alien_0)

alien_0, -
. , -
:
{'color': 'green', 'points': 5}

, -
, ,
.


,
, , . -
, :
alien_0 = {'color': 'green'}
print("The alien is " + alien_0['color'] + ".")

alien_0['color'] = 'yellow'
print("The alien is now " + alien_0['color'] + ".")

alien_0, ;
, 'color', 'yellow'.
, :
The alien is green.
The alien is now yellow.

: ,
. ,
, -
:
alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print("Original x-position: " + str(alien_0['x_position']))
# .
# .

if alien_0['speed'] == 'slow':
x_increment = 1
elif alien_0['speed'] == 'medium':
x_increment = 2
else:
# .
x_increment = 3
# .
105

alien_0['x_position'] = alien_0['x_position'] + x_increment


print("New x-position: " + str(alien_0['x_position']))

( x y) -
'medium'. ,
.
x_position.
if-elif-else ,
; x_increment.
('slow'),
; ('medium') ;
, ('fast') .
x_position , -
x_position.
:
Original x-position: 0
New x-position: 2

, -
. , ,
:
alien_0['speed'] = fast

if-elif-else x_increment
.


, , ,
del. -
.
, alien_0 'points'
:
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

del alien_0['points']
print(alien_0)

Python 'points' alien_0,


, . , 'points'
5 , -
:
{'color': 'green', 'points': 5}
{'color': 'green'}
106 6

, .



( ). -
. ,
-
. :
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

. -
, . ,
, Enter -
.
( ) , -
. Enter
, .
,

, . -
,
.

,
. -

.

:
favorite_languages.py
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
print("Sarah's favorite language is " +
favorite_languages['sarah'].title() +
".")
107

, Sarah,
:
favorite_languages['sarah']

, ,
:
Sarah's favorite language is C.

, print
. print , -
-
. , ,
(+) . Enter, Tab

print. , -
print .


6-1. : -
. , , , .
, first_name, last_name, age city.
, .
6-2. : .
. -
. -
. ,
.
6-3. : Python
( , ).
,
. ,
.
.
, , ;
, .
(\n) --
.


Python , -
. ,
Python .
-,
. , -
.
108 6


,
, -.
, :
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}

, ,
user_0 .
?
for:
user.py
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}

for key, value in user_0.items():


print("\nKey: " + key)
print("Value: " + value)
, for ,
,
.
:
for k, v in user_0.items()

for ,
items(), .
for . -
v,
w. "\n" print ,
:
Key: last
Value: fermi

Key: first
Value: enrico

Key: username
Value: efermi

,
. Python
109

;
.
-
, favorite_languages.py . 106: , -
.
favorite_languages ,
. , -
, key value name
language. ,
:
favorite_languages.py
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

for name, language in favorite_languages.items():


print(name.title() + "'s favorite language is " +
language.title() + ".")

Python .
name, -
language. ,
print .
:
Jen's favorite language is Python.
Sarah's favorite language is C.
Phil's favorite language is Python.
Edward's favorite language is Ruby.

,
.


keys() ,
. favorite_languages
, :
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in favorite_languages.keys():
print(name.title())
110 6

Python favorite_languages
name. -
, :
Jen
Sarah
Phil
Edward

,
,
for name in favorite_languages:

for name in favorite_languages.keys():

keys(), ,
, .
, ,
.
. , ,
, ,
:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

friends = ['phil', 'sarah']


for name in favorite_languages.keys():
print(name.title())

if name in friends:
print(" Hi " + name.title() +
", I see your favorite language is " +
favorite_languages[name].title() + "!")

, .
, -
, . ,
.
, name
. ,
:
Edward
Phil
Hi Phil, I see your favorite language is Python!
Sarah
111

Hi Sarah, I see your favorite language is C!


Jen

keys() , -
:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")

keys() : ,
, 'erin' . -
, :
Erin, please take our poll!


,
. ,
, ,
.

, for.
sorted():
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

for name in sorted(favorite_languages.keys()):


print(name.title() + ", thank you for taking the poll.")

for for, ,
dictionary.keys() sorted().
Python
, . ,
, :
Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.
112 6


, ,
values() . ,
, ,
, :
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

print("The following languages have been mentioned:")


for language in favorite_languages.values():
print(language.title())

for
language. :
The following languages have been mentioned:
Python
C
Python
Ruby

. -
,
.
, (set).
, :
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

print("The following languages have been mentioned:")


for language in set(favorite_languages.values()):
print(language.title())

, , set(), Python
.
set() favorite_languages.
values(). -
, :
The following languages have been mentioned:
Python
C
Ruby
113

Python
, ,
.


6-4. 2: , , ,
6-3, print ,
. , ,
Python.
.
6-5. : ,
. nile: egypt.
,
The Nile runs through Egypt.
, .
, .
6-6. : favorite_languages.py (. 106).
, -
. ,
, , .
, . -
, . -
, .

-
.
. ,
.
,
.


alien_0 ,
,
, . ? -
, , -
.
:
aliens.py
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
114 6

aliens = [alien_0, alien_1, alien_2]

for alien in aliens:


print(alien)

, -
. aliens. ,
:
{'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 10}
{'color': 'red', 'points': 15}

, ,
.
range() 30 :
# .
aliens = []
# 30 .
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)

# 5 :
for alien in aliens[:5]:
print(alien)
print("...")

# .
print("Total number of aliens: " + str(len(aliens)))

, ,
. range() ,
Python, .
, aliens .
,
( ,
30 ):
{'speed': 'slow', 'color': 'green', 'points': 5}
{'speed': 'slow', 'color': 'green', 'points': 5}
{'speed': 'slow', 'color': 'green', 'points': 5}
{'speed': 'slow', 'color': 'green', 'points': 5}
{'speed': 'slow', 'color': 'green', 'points': 5}
...
Total number of aliens: 30

, Python -
,
.
? , -
.
115

, for if -
. , ,
10 ,
:
# .
aliens = []

# 30 .
for alien_number in range (0,30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)

for alien in aliens[0:3]:


if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10

# 5 :
for alien in aliens[0:5]:
print(alien)
print("...")

, , -
.
('green'), , if, -
, . ,
('yellow'), ('medium'), -
10 :
{'speed': 'medium', 'color': 'yellow', 'points': 10}
{'speed': 'medium', 'color': 'yellow', 'points': 10}
{'speed': 'medium', 'color': 'yellow', 'points': 10}
{'speed': 'slow', 'color': 'green', 'points': 5}
{'speed': 'slow', 'color': 'green', 'points': 5}
...

, elif
15 .
, :
for alien in aliens[0:3]:
if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10
elif alien['color'] == 'yellow':
alien['color'] = 'red'
alien['speed'] = 'fast'
alien['points'] = 15

,
. ,
116 6

, -
user.py . 108, users.
,
.


,
. , .
, -
.
.
:
. ,
'toppings'. ,
'toppings', -
. :
pizza.py
# .
pizza = {
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}

# .
print("You ordered a " + pizza['crust'] + "-crust pizza " +
"with the following toppings:")

for topping in pizza['toppings']:


print("\t" + topping)

.
'crust' 'thick'.
'toppings' -, -
. . -
, 'toppings', Python
.
, :
You ordered a thick-crust pizza with the following toppings:
mushrooms
extra cheese

,
. -
,
.
, ,
117

( .) for
, :
favorite_languages.py
favorite_languages = {
'jen': ['python', 'ruby'],
'sarah': ['c'],
'edward': ['ruby', 'go'],
'phil': ['python', 'haskell'],
}

for name, languages in favorite_languages.items():


print("\n" + name.title() + "'s favorite languages are:")
for language in languages:
print("\t" + language.title())

, , , -
. -
, .
languages
, ,
. -
.

:
Jen's favorite languages are:
Python
Ruby

Sarah's favorite languages are:


C

Phil's favorite languages are:


Python
Haskell

Edward's favorite languages are:


Ruby
Go

, for
if ,
( len(languages)).
, -
(, Sarahs favorite language is C).


. -
, -
, ,
, .
118 6


,
. , -
, -
. ,
, .
: , .
,
, :
many_users.py
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}

for username, user_info in users.items():


print("\nUsername: " + username)
full_name = user_info['first'] + " " + user_info['last']
location = user_info['location']
print("\tFull name: " + full_name.title())
print("\tLocation: " + location.title())

users, :
'aeinstein' 'mcurie'. , ,
, -
. users Python
username, , , -
user_info.
.
. user_info, -
, : 'first',
'last' 'location'. -
,
:
Username: aeinstein
Full name: Albert Einstein
Location: Princeton
Username: mcurie
Full name: Marie Curie
Location: Paris
119

.
Python , -
.
, for .


6-7. : , 6-1 (. 107).
, ,
people. .
.
6-8. : ,
. -
. pets.
. .
6-9. : favorite_places.
, ,
. ,
. , -
.
6-10. : 6-2 (. 107),
. -
.
6-11. : cities. -
. ;
, , -
, . -
country, population fact.
.
6-12. : , , ,
.
: ,
.


. , -
, .
, . -
,
.
while
. ,
- : -
.
7 while

, , .
, -
. : , ,
. ,
. -
; ,
, , .
, (
), . ,
. -
input().
,
; -
. while Python ,
.
-
, -
.

input()
input() ,
. , Python -
, .
, ,
:
parrot.py
message = input("Tell me something, and I will repeat it back to you: ")
print(message)

input() : ( ),
, , .

. ,
input() 121

, Enter.
message, print(message) :
Tell me something, and I will repeat it back to you: Hello everyone!
Hello everyone!


Sublime Text , .
Sublime Text ,
. . Python , . 29.


, input(),
, , ,
. ,
, . :
greeter.py
name = input("Please enter your name: ")
print("Hello, " + name + "!")

( ),
, , ,
. :
Please enter your name: Eric
Hello, Eric!

. , -
, .
input(): -
, input().
greeter.py
prompt = "If you tell us who you are, we can personalize the messages you see."
prompt += "\nWhat is your first name? "

name = input(prompt)
print("\nHello, " + name + "!")

.
prompt. -
+= , prompt, .
prompt ( -
):
If you tell us who you are, we can personalize the messages you see.
What is your first name? Eric

Hello, Eric!
122 7 while

int()

input() Python , -
, .
:
>>> age = input("How old are you? ")
How old are you? 21
>>> age
'21'

21, , Python
age, '21' .
, , , Python -
.
:
>>> age = input("How old are you? ")
How old are you? 21
>>> age >= 18
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() >= int()

, Python
, : '21',
age, 18; .
int(),
. int()
:
>>> age = input("How old are you? ")
How old are you? 21
>>> age = int(age)
>>> age >= 18
True

21 ,
int() . Python
: age (
21) 18. age 18 -
, True.
int() ? ,
, -
:
rollercoaster.py
height = input("How tall are you, in inches? ")
height = int(height)
input() 123

if height >= 36:


print("\nYou're tall enough to ride!")
else:
print("\nYou'll be able to ride when you're a little older.")

height 36, height = int(height)


. -
36, ,
:
How tall are you, in inches? 71
You're tall enough to ride!

, -
,
.


-
(%), :
>>> 4 % 3
1
>>> 5 % 3
2
>>> 6 % 3
0
>>> 7 % 3
1

% ;
.
, 0, % -
0. ,
:
even_or_odd.py
number = input("Enter a number, and I'll tell you if it's even or odd: ")
number = int(number)

if number % 2 == 0:
print("\nThe number " + str(number) + " is even.")
else:
print("\nThe number " + str(number) + " is odd.")

2. , 2
0 (number % 2 == 0), , .
Enter a number, and I'll tell you if it's even or odd: 42

The number 42 is even.


124 7 while

Python 2.7
Python 2.7, -
raw_input().
, input() Python 3.
Python 2.7 input(), -
Python . Python
, -
; , .
, Python2.7 input() raw_input().


7-1. : , , -
. (,
Let me see if I can find you a Subaru).
7-2. : , ,
. 8,
, . ,
.
7-3. , 10: , 10 .

while
for
. , while -
, .

while
while .
, 1 5:
counting.py
current_number = 1
while current_number <= 5:
print(current_number)
current_number += 1

1, current_number
1. while, ,
current_number 5.
current_number 1 current_number+=1.
( += current_number =
current_number + 1.)
, current_number <= 5 .
1 5, Python 1, 1, current_
number 2. 2 5, Python 2 -
while 125

1 . . current_number 5, -
, :
1
2
3
4
5

while . ,
: while , -
, , .
- ,
, , while
.


parrot.py ,
, while. -
, ,
:
parrot.py
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
message = ""
while message != 'quit':
message = input(prompt)
print(message)

, ,
: (
'quit'). message , -
. message
"" ,
while. -
while, message 'quit',
. Python ,
. ,
message . ,
Python ;
, while. while ,
message 'quit'.
message , Python
. message = input(prompt) Python
, .
message print; Python -
while. 'quit',
126 7 while

, Python .
'quit' Python while, :
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello everyone!
Hello everyone!

Tell me something, and I will repeat it back to you:


Enter 'quit' to end the program. Hello again.
Hello again.

Tell me something, and I will repeat it back to you:


Enter 'quit' to end the program. quit
quit

, , 'quit',
. if -
:
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
message = ""
while message != 'quit':
message = input(prompt)

if message != 'quit':
print(message)

-
, :
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. Hello everyone!
Hello everyone!

Tell me something, and I will repeat it back to you:


Enter 'quit' to end the program. Hello again.
Hello again.

Tell me something, and I will repeat it back to you:


Enter 'quit' to end the program. quit

,
. ,
?
, : -
; ; ,
, ..
.
while
.
while 127

,
-. , -
. ,
, True, ,
False.
while :
True. ( , -
, False) .
parrot.py . ,
active ( ), ,
:
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "

active = True
while active:
message = input(prompt)

if message == 'quit':
active = False
else:
print(message)

active True,
. while,
while ; -
. active True,
.
if while message ,
. 'quit' , active
False, while .
, 'quit' , .
-
, while.
, , ,
( elif) ,
active False.
, -
, .
active False, -
, ,
.

break
while
, break. break
128 7 while

; ,
, .
, , -
. while, break,
'quit':
cities.py
prompt = "\nPlease enter the name of a city you have visited:"
prompt += "\n(Enter 'quit' when you are finished.) "

while True:
city = input(prompt)

if city == 'quit':
break
else:
print("I'd love to go to " + city.title() + "!")

, while True ,
break.
,
'quit'. 'quit' break, Python
:
Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) New York
I'd love to go to New York!

Please enter the name of a city you have visited:


(Enter 'quit' when you are finished.) San Francisco
I'd love to go to San Francisco!

Please enter the name of a city you have visited:


(Enter 'quit' when you are finished.) quit


break Python. , -
for .

continue
-
, continue
. , , 1
10, :
counting.py
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
while 129

continue

print(current_number)

current_number 0. 10,
Python while. 1 -
, current_number 1. if
current_number 2. 0 ( ,
current_number 2), continue Python -
.
2, , Python
:
1
3
5
7
9


while , -
. , 1 5:
counting.py
x = 1
while x <= 5:
print(x)
x += 1

x += 1 (. ),
:
# !
x = 1
while x <= 5:
print(x)

x 1, -
. x <= 5
True, while :
1
1
1
1

,
. -
, Ctrl+C
.
130 7 while

, while -
, , . -
,
. , -
, . ,
,
False break.

, Sublime Text .
; , -
.


7-4. : ,
, 'quit. -
, .
7-5. : -
. 3 ;
3 12 $10; , 12, $15.
, .
7-6. : 7-4 7-5,
.
while.

active.
break, quit.
7-7. : , , .
( , Ctrl+C .)

while
,
. ,
. while
. ,
, while
.
for , , , -
, Python -
. ,
while. while ,

.
, -
.
while 131

? : while
,
. :
confirmed_users.py
# :
# .
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []

# ,
# . , ,
# .
while unconfirmed_users:
current_user = unconfirmed_users.pop()

print("Verifying user: " + current_user.title())


confirmed_users.append(current_user)

# .
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
print(confirmed_user.title())

:
. while -
, unconfirmed_users .
pop()
unconfirmed_users. unconfirmed_users
Candace; , -
current_user confirmed_users .
Brian Alice.
,
.
.
, -
, :
Verifying user: Candace
Verifying user: Brian
Verifying user: Alice

The following users have been confirmed:


Candace
Brian
Alice


3 remove()
. remove() ,
132 7 while

. -
?
, pets, 'cat' .
, while
, 'cat':
pets.py
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)

while 'cat' in pets:


pets.remove('cat')

print(pets)

, 'cat'.
Python while, 'cat' -
. Python
'cat', while, ,
'cat' , . -
'cat' , , 'cat'
; Python :
['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
['dog', 'dog', 'goldfish', 'rabbit']

,
while
. , -
. -
,
:
mountain_poll.py
responses = {}

# .
polling_active = True

while polling_active:
# .
name = input("\nWhat is your name? ")
response = input("Which mountain would you like to climb someday? ")

# :
responses[name] = response

# .
while 133

repeat = input("Would you like to let another person respond? (yes/ no) ")
if repeat == 'no':
polling_active = False

# , .
print("\n--- Poll Results ---")
for name, response in responses.items():
print(name + " would like to climb " + response + ".")

(responses)
(polling_active), , . polling_active
True, Python while.
,
. responses
, , -
. ,
while. , polling_active
False, while ,
.
, -
:
What is your name? Eric
Which mountain would you like to climb someday? Denali
Would you like to let another person respond? (yes/ no) yes

What is your name? Lynn


Which mountain would you like to climb someday? Devil's Thumb
Would you like to let another person respond? (yes/ no) no

--- Poll Results ---


Lynn would like to climb Devil's Thumb.
Eric would like to climb Denali.


7-8. : sandwich_orders, -
. finished_sandwiches.
(-
, I made your tuna sandwich). -
finished_sandwiches.
, .
7-9. : sandwich_orders 7-8,
, pastrami . -
, ,
while pastrami sandwich_orders. ,
finished_sandwiches pastrami .
7-10. : , ,
. .
134 7 while

input() ,
. -
,
while.
while: , break
continue. , while

.
while .
8 . -
, .
, .
,
,
.
8

,
. ,
, , . -
,
; ,
, Python ,
. , , -
, .
-
. , ,
, , -
( .) ,
, ,
.


greet_user(), :
greeter.py
def greet_user():
""" ."""
print("Hello!")

greet_user()
. -
def Python, . -
, , ,
.
. greet_user(),
,
. (, .) ,
.
, def greet_user():, -
.
136 8

. ;
Python
.

print("Hello!") . . , greet_user()
: print("Hello!").
, . -
Python . ,
, ,
, . -
,
greet_user(). , Hello!:
Hello!


greet_user()
! , .
username def greet_
user(). username ,
. ,
. greet_user() (-
, 'jesse') :
def greet_user(username):
""" ."""
print("Hello, " + username.title() + "!")

greet_user('jesse')

greet_user('jesse') greet_user()
, print.
:
Hello, Jesse!

greet_user('sarah') greet_user()
'sarah', Hello, Sarah!
greet_user()
.


greet_user() ,
username. -
( ),
.
137

username greet_user() ,
, . 'jesse'
greet_user('jesse') , ,
. , ,
, . 'jesse'
greet_user(),
username.

. -
, , ,
, .


8-1. : display_message() , -
. , -
.
8-2. : favorite_book(), -
title. One of my favorite books is Alice in
Wonderland. , -
.


, ,
.
.
, ;
; , -
. .



.
. , -
, .
, , -
. :
pets.py
def describe_pet(animal_type, pet_name):
""" ."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('hamster', 'harry')
138 8

,
(animal_type) (pet_name). describe_pet() -
. 'hamster'
animal_type, 'harry'
pet_name . -
:
I have a hamster.
My hamster's name is Harry.


, .
describe_pet():
def describe_pet(animal_type, pet_name):
""" ."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')

describe_pet() 'dog' 'willie'.


Python 'dog'
animal_type, 'willie' pet_name.
, , -
:
I have a hamster.
My hamster's name is Harry.

I have a dog.
My dog's name is Willie.

.
.
, ,
. -
10 ,
.
.
Python , ,
.


-
, :
def describe_pet(animal_type, pet_name):
""" ."""
139

print("\nI have a " + animal_type + ".")


print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('harry', 'hamster')

, .
'harry' ,
animal_type, 'hamster' pet_name. -
:
I have a harry.
My harry's name is Hamster.

, ,
-
.


,
. , -
. -
,
.
pets.py
describe_pet():
def describe_pet(animal_type, pet_name):
""" ."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet(animal_type='hamster', pet_name='harry')
describe_pet() . -
Python,
. Python , 'hamster'
animal_type, 'harry'
pet_name.
,
Python , .
:
describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(pet_name='harry', animal_type='hamster')

-
.
140 8


-
. ,
, Python , -
. ,
, ,
.
.
, , describe_pet() -
, animal_type 'dog'.
describe_pet()
:
def describe_pet(pet_name, animal_type='dog'):
""" ."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet(pet_name='willie')

describe_pet() animal_type
'dog'.
animal_type, Python ,
'dog':
I have a dog.
My dog's name is Willie.

: -
. -
,
. Python
, ,
.
.

:
describe_pet('willie')
, . -
'willie' -
, pet_name. animal_type ,
Python 'dog'. -
, ,
:
describe_pet(pet_name='harry', animal_type='hamster')
animal_type , Python -
.
141

,
, . ,
Python .


, -
, -
. describe_pets()
:
def describe_pet(pet_name, animal_type='dog'):

pet_name -
, , -
. ,
animal_type ,
, .
:
describe_pet('willie')
describe_pet(pet_name='willie')

describe_pet('harry', 'hamster')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')

, .

, . -
, , .


, -
. -
, ,
. ,
describe_pet() :
def describe_pet(animal_type, pet_name):
""" ."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet()
142 8

Python , ,
:
Traceback (most recent call last):
File "pets.py", line 6, in <module>
describe_pet()
TypeError: describe_pet() missing 2 required positional arguments:
'animal_
type' and 'pet_name'

, ,
- . ,
. Python , ,
.
, , ,
.
Python , -
, . ,
.
Python ,
, .
,
,
.

8-3. : make_shirt(), ,
.
. . -
.
8-4. : make_shirt(),
L, I love Python..
L , .
8-5. : describe_city(), -
. (, Reykjavik is in Iceland). -
.
, .


.
, . ,
, . return
, .

, .
143


,
:
formatted_name.py
def get_formatted_name(first_name, last_name):
""" ."""
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)

get_formatted_name() .
,
full_name . full_name
, .
, , -
, .
musician .
, :
Jimi Hendrix

,
:
print("Jimi Hendrix")

, , -
, ,
get_formatted_name(), .
, ,
.


, , -
,
, . ,
. ,
get_formatted_name(), .
:
def get_formatted_name(first_name, middle_name, last_name):
""" ."""
full_name = first_name + ' ' + middle_name + ' ' + last_name
return full_name.title()

musician = get_formatted_name('john', 'lee', 'hooker')


print(musician)
144 8

, .
, .
, , :
John Lee Hooker

, ,
.
, middle_name
; ,
. get_formatted_name() , -
middle_name
:
def get_formatted_name(first_name, last_name, middle_name=''):
""" ."""
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_
name
else:
full_name = first_name + ' ' + last_name
return full_name.title()

musician = get_formatted_name('jimi', 'hendrix')


print(musician)

musician = get_formatted_name('john', 'hooker', 'lee')


print(musician)

.
, .
, -
, .
, . Python -
, ,
, middle_name True .
, , .
-
, musician .
, if else .
,
, musician
.
. -
,
. -
.
,
, :
145

Jimi Hendrix
John Lee Hooker


, ,
(, ). , -
, :
person.py
def build_person(first_name, last_name):
""" ."""
person = {'first': first_name, 'last': last_name}
return person

musician = build_person('jimi', 'hendrix')


print(musician)

build_person() -
. first_name 'first',
last_name 'last' .
.
, :
{'first': 'jimi', 'last': 'hendrix'}

-
, ( -
). 'jimi' 'hendrix' .
,
: , , -
, . ,
:
def build_person(first_name, last_name, age=''):
""" ."""
person = {'first': first_name, 'last': last_name}
if age:
person['age'] = age
return person

musician = build_person('jimi', 'hendrix', age=27)


print(musician)

age, -
.
, .
, ,
.
146 8

while
Python,
. , get_formatted_name() while,
. ,
, :
greeter.py
def get_formatted_name(first_name, last_name):
""" ."""
full_name = first_name + ' ' + last_name
return full_name.title()

# !
while True:
print("\nPlease tell me your name:")
f_name = input("First name: ")
l_name = input("Last name: ")

formatted_name = get_formatted_name(f_name, l_name)


print("\nHello, " + formatted_name + "!")

get_formatted_name(),
. while -
.
while : -
. ?
-
, . break
:
def get_formatted_name(first_name, last_name):
""" ."""
full_name = first_name + ' ' + last_name
return full_name.title()

while True:
print("\nPlease tell me your name:")
print("(enter 'q' at any time to quit)")

f_name = input("First name: ")


if f_name == 'q':
break

l_name = input("Last name: ")


if l_name == 'q':
break

formatted_name = get_formatted_name(f_name, l_name)


print("\nHello, " + formatted_name + "!")

, , -
,
147

.
, 'q':
Please tell me your name:
(enter 'q' at any time to quit)
First name: eric
Last name: matthes

Hello, Eric Matthes!

Please tell me your name:


(enter 'q' at any time to quit)
First name: q


8-6. : city_country(), -
. Santiago, Chile.

.
8-7. : make_album(), -
.
, .
, . -
, ,
.
make_album()
. , -
.
.
8-8. : 8-7.
while, . -
make_album()
. while.


,
(, ).
. ,
.
, .
greet_users(),
:
greet_users.py
def greet_users(names):
""" ."""
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
148 8

usernames = ['hannah', 'ty', 'margot']


greet_users(usernames)

greet_users() -
, names.
.
usernames, greet_
users() :
Hello, Hannah!
Hello, Ty!
Hello, Margot!

, .
, -
.


, .
, , , -
.
, 3D- , -
. ,
. , :
printing_models.py
# , .
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []

# .
# completed_models.
while unprinted_designs:
current_design = unprinted_designs.pop()
# 3D-.
print("Printing model: " + current_design)
completed_models.append(current_design)

# .
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)

completed_models,
. unprinted_designs
, while :
, current_design,
, . -
.
:
149

Printing model: dodecahedron


Printing model: robot pendant
Printing model: iphone case

The following models have been printed:


dodecahedron
robot pendant
iphone case

: -
, .
; .
, :
def print_models(unprinted_designs, completed_models):
"""
, .
completed_models.
"""
while unprinted_designs:
current_design = unprinted_designs.pop()

# 3D-.
print("Printing model: " + current_design)
completed_models.append(current_design)

def show_completed_models(completed_models):
""" ."""
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)

unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']


completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)

print_models() :
. -
,
. show_completed_models()
: . show_completed_
models() .
, ,
. , , -
; .

, :
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
150 8

-
. , ,
. print_models()
; , print_models() . -
show_completed_models(), ,
.

.
-
, .
, print_models(). ,
, ,
.
.
,
.
, .
.
, ,
.
, . -
.


. ,
,
, . , -
. ,
unprinted_designs,
; . -
. ,
, ,
.
, :
_(_[:])

[:] .
unprinted_designs print_models.py ,
print_models() :
print_models(unprinted_designs[:], completed_models)

print_models() ,
.
unprinted_designs, . completed_models
151

, ,
.
, -
(
). ,

( ).


8-9. : . show_
magicians(), .
8-10. : 8-9.
make_great(), ,
Great. show_magicians() ,
.
8-11. : 8-10. -
make_great() .
, .
show_magicians() , , -
,
Great.


,
. , Python
.
. -
, , -
. *toppings,
, :
pizza.py
def make_pizza(*toppings):
""" ."""
print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

*toppings Python -
toppings .
print , Python
, .
. : Python
,
:
152 8

('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese')
print ,
:
def make_pizza(*toppings):
""" ."""
print("\nMaking a pizza with the following toppings:")
for topping in toppings:
print("- " + topping)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

,
:
Making a pizza with the following toppings:
- pepperoni

Making a pizza with the following toppings:


- mushrooms
- green peppers
- extra cheese

,
.


, -
,
. Python -
,
.
, ,
*toppings:
def make_pizza(size, *toppings):
""" ."""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

Python
size. , , toppings.
size,
.
153

,
: ,
:
Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:


- mushrooms
- green peppers
- extra cheese


,
, .
, ,
. -
: , ,
, . build_profile()
, -
:
user_profile.py
def build_profile(first, last, **user_info):
""" ."""
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile

user_profile = build_profile('albert', 'einstein',


location='princeton',
field='physics')
print(user_profile)

build_profile() ,
.
**user_info Python -
user_info .
user_info
, .
build_profile() profile
. ,
. -
user_info
profile. , profile
.
154 8

build_profile() 'albert' , -
'einstein' , location='princeton'
field='physics'. user_profile
:
{'first_name': 'albert', 'last_name': 'einstein',
'location': 'princeton', 'field': 'physics'}

,
. ,
.

, . -
,
.
, ;
, .

.


8-12. : , . -
,
, . -
.
8-13. : user_profile.py.
build_profile(), ,
.
8-14. : -
. ,
.
(,
). :
car = make_car(subaru, outback, color=blue, tow_package=True)
,
.


,
. ,
. -
, ,
. import Python, -
.

. ,
155

. , -
,
. -
, .
; -
.


, .
.py, ,
. -
make_pizza(). pizza.py ,
make_pizza():

pizza.py
def make_pizza(size, *toppings):
""" ."""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)

making_pizzas.py pizza.
py. ,
make_pizza():

making_pizzas.py
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

import pizza Python -


pizza.py . -
, , Python
. :
, pizza.py, making_pizzas.py.
,
(pizza), (make_pizza()), . -
, , -
:
Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:


- mushrooms
- green peppers
- extra cheese
156 8

, import -
, :
_._()


. -
:
from _ import _

,
:
from _ import _0, _1, _2

, -
, making_pizzas.py :
from pizza import make_pizza

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

-
. make_pizza() import,
.



,
(alias) . -
.
make_pizza() mp(),
make_pizza as mp.
as , :
from pizza import make_pizza as mp

mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')

import make_pizza() mp()


. , make_pizza(), -
mp() Python make_pizza()
make_pizza(), -
.
:
from _ import _ as
157


.
, p pizza -
. p.make_pizza() , pizza.
make_pizza():
import pizza as p

p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

pizza import p ,
. p.make_
pizza() pizza.make_pizza(); -

. , , -
, ,
.
:
import _ as


Python ;
*:
from pizza import *

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

import Python
pizza .
.
, -
; ,
, -
. Python
,
.
-

. , .
, import ,
:
from _ import *
158 8


.
, -
.
, .
.
, ,
. -
. -
, , .
, ,
, , ,
, .
, -
:
def _(_0, _1='__')


:
_(_0, _1='')

PEP 8 (https://www.python.org/dev/peps/pep-0008/) -
79 ,
. - -
79 , Enter
. Tab,
,
.
-
, :
def _(
_0, _1, _2,
_3, _4, _5):
...

,
. ,
.
import .
: ,
.


8-15. : print_models.py -
printing_functions.py. import print_models.py -
, .
159

8-16. :
. .
:
import _
from _ import _
from _ import _ as
import _ as
from _ import *
8-17. : ,
. , ,
.

,
, . ,
-
. , ,
, .
, , if while. -
, ,
.
,
.
, -
, .
. , -
, , , .

, . , -
, ,
. ,
; ,
.
,
, .
, , ,
.
. -
,
,
. , -
.
, .
9 .
, .
9

-
. -
- ,
,
.
.
,
;
. ,
-
.
; -
, .
. ,
, ,
.
,
; -
. -
, ,
.
- -
.
, ,
, . , ,
, -
, .
, ,
.
, ,
. ,
.
161


.
Dog, - ,
. ? . ,
.
( ) ( )
Dog,
. Python, , . -
, ,
.

Dog
, Dog,
; , sit() roll_over():
dog.py
class Dog():
""" ."""

def __init__(self, name, age):


""" name age."""
self.name = name
self.age = age

def sit(self):
""" ."""
print(self.name.title() + " is now sitting.")
def roll_over(self):
""" ."""
print(self.name.title() + " rolled over!")

, , .
,
. Dog. -
, , Python
. ,
. .

__init__()
, , . ,
, ; -
. __init__() ,

Dog .
;
Python .
162 9

__init__() : self, name age. -


self ;
. ,
__init__() ( Dog) -
self. , -
, self ;
.
Dog, Python __init__() Dog.
Dog() ; self ,
. ,
Dog,
name age.
, , self. -
self ,
,
. self.name = name ,
name, name, -
. self.age = age.
, ,
.
Dog : sit() roll_over() .
( ),
self . ,
, . sit() roll_over()
,
.
: ,
-
. ,
, -
.

Python 2.7

Python 2.7 -
object:
class ClassName(object):
...

Python 2.7 -
Python 3, .
, Python 2.7 Dog :
class Dog(object):
...
163


, . -
, Dog ,
.
, :
class Dog():
...
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")

Dog -
. Python
'willie' 6. Python -
__init__() Dog 'willie' 6. __init__()
, , name
age . __init__() return,
Python , .
my_dog. -
: , ,
(, Dog), , ,
(, my_dog), , .


. -
name my_dog:
my_dog.name

Python. ,
Python . Python -
my_dog name, my_dog.
, self.name Dog. -
age. print my_dog.name.
title() 'willie' ( name my_dog)
. print str(my_dog.age) 6,
age my_dog, .
my_dog:
My dog's name is Willie.
My dog is 6 years old.


Dog -
, Dog:
164 9

class Dog():
...

my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()

, ( my_dog)
, . my_dog.sit() Python sit()
Dog . my_dog.roll_over()
.
:
Willie is now sitting.
Willie rolled over!

. -
(, name, age, sit() roll_over()),
, , .


, .
Dog your_dog:
class Dog():
...

my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)

print("My dog's name is " + my_dog.name.title() + ".")


print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()

print("\nYour dog's name is " + your_dog.name.title() + ".")


print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()

Willie Lucy. -

:
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.

Your dog's name is Lucy.


Your dog is 3 years old.
Lucy is now sitting.

, Python
Dog .
,
165


9-1. : Restaurant. __init__() Restaurant -
: restaurant_name cuisine_type. describe_
restaurant(), , open_restaurant(),
, .
restaurant.
, .
9-2. : 9-1. ,
describe_restaurant().
9-3. : User. first_name last_
name, , -
. describe_user(), -
. greet_user()
.
, .
.


. -
,
, .
, . -
,
.

Car
, . -
, :
car.py
class Car():
""" ."""
def __init__(self, make, model, year):
""" ."""
self.make = make
self.model = model
self.year = year

def get_descriptive_name(self):
""" ."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()

my_new_car = Car('audi', 'a4', 2016)


print(my_new_car.get_descriptive_name())
166 9

Car __init__(); -
self, Dog. : make, model
year. __init__() , -
, .
Car -,
.
get_descriptive_name(),
, - .
.
self.make,
self.model self.year.
Car,
my_new_car. get_descriptive_name() , -
:
2016 Audi A4
, , -
, .


,
0 . (,
) __init__();

.
odometer_reading,
0. read_odometer()
:
class Car():

def __init__(self, make, model, year):


""" ."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0

def get_descriptive_name(self):
...

def read_odometer(self):
""" ."""
print("This car has " + str(self.odometer_reading) + " miles on it.")

my_new_car = Car('audi', 'a4', 2016)


print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
167

Python __init__() ,
-, ,
. Python odometer_
reading 0 .
read_odometer() ,
.
0:
2016 Audi A4
This car has 0 miles on it.

, 0,
.


:
,
( ) .
.


, -
. 23:
class Car():
...

my_new_car = Car('audi', 'a4', 2016)


print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

odometer_
reading .
Python my_new_car, odometer_
reading 23:
2016 Audi A4
This car has 23 miles on it.

,
, .


, .
, -
, .
168 9

update_odometer()
:
class Car():
...

def update_odometer(self, mileage):


""" ."""
self.odometer_reading = mileage

my_new_car = Car('audi', 'a4', 2016)


print(my_new_car.get_descriptive_name())

my_new_car.update_odometer(23)
my_new_car.read_odometer()

Car , update_odometer().
self.odometer_reading.
update_odometer() 23
( mileage ).
23, read_odometer()
:
2016 Audi A4
This car has 23 miles on it.

update_odometer() ,
.
, ,
:
class Car():
...

def update_odometer(self, mileage):


"""
.
.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
update_odometer() .
mileage , self.odometer_reading,
.
, -
.


(-
). ,
169

100 .
:
class Car():
...

def update_odometer(self, mileage):


--snip--

def increment_odometer(self, miles):


""" ."""
self.odometer_reading += miles

my_used_car = Car('subaru', 'outback', 2013)


print(my_used_car.get_descriptive_name())

my_used_car.update_odometer(23500)
my_used_car.read_odometer()

my_used_car.increment_odometer(100)
my_used_car.read_odometer()

increment_odometer()
self.odometer_reading .
my_used_car. 23500;
update_odometer(),
23500 . increment_odometer(), -
100, 100 ,
:
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.

,
;
.

(, -
), , , -
.
, .


9-4. : 9-1 (. 165).
number_served 0;
. restaurant. number_served,
.
set_number_served(), -
. , .
170 9

increment_number_served(),
. ,
, .
9-5. : login_attempts User 9-3
(. 165). increment_login_attempts(), login_
attempts 1. reset_login_attempts(), -
login_attempts.
User increment_login_attempts() . -
login_attempts, , -
, reset_login_attempts(). login_attempts -
, .

. ,
, -
, . , ,
.
, . -
,
.

__init__() -
, Python -,
-. __init__() --
.
, . -
,
ElectricCar Car, .
,
.
ElectricCar, ,
Car:
electric_car.py
class Car():
""" ."""

def __init__(self, make, model, year):


self.make = make
self.model = model
self.year = year
self.odometer_reading = 0

def get_descriptive_name(self):
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
171

def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")

def update_odometer(self, mileage):


if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")

def increment_odometer(self, miles):


self.odometer_reading += miles

class ElectricCar(Car):
""" , ."""
def __init__(self, make, model, year):
""" -."""
super().__init__(make, model, year)

my_tesla = ElectricCar('tesla', 'model s', 2016)


print(my_tesla.get_descriptive_name())

Car. - -
,
- . -
ElectricCar. -
. __init__() ,
Car.
super() , Python
. Python
__init__() , ElectricCar, -
ElectricCar -. super
: - ,
- .
, ,
,
Car. ElectricCar
my_tesla. __init__(), -
ElectricCar, Python
__init__(), - Car. -
'tesla', 'model s' 2016.
__init__() ,
. ,
, :
2016 Tesla Model S

ElectricCar , Car;
, .
172 9

Python 2.7
Python 2.7 . ElectricCar
:
class Car(object):
def __init__(self, make, model, year):
...

class ElectricCar(Car):
def __init__(self, make, model, year):
super(ElectricCar, self).__init__(make, model, year)
...

super() : - -
self. , Python
. Python 2.7,
, object.

-
-, -, -
, ,
.
, (, -
), :
class Car():
...

class ElectricCar(Car):
""" , ."""
def __init__(self, make, model, year):
"""
-.
, .
"""
super().__init__(make, model, year)
self.battery_size = 70

def describe_battery(self):
""" ."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")

my_tesla = ElectricCar('tesla', 'model s', 2016)


print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

self.battery_size,
, 70. -
, ElectricCar ( Car).
describe_battery(), -
173

. ,
:
2016 Tesla Model S
This car has a 70-kWh battery.

ElectricCar . -
,
. ,
( ), Car -
ElectricCar.
Car, ElectricCar ,
.

-
,
, , . -
, -. Python
, .
, Car fill_gas_tank(). -
, . -
, :
def ElectricCar(Car):
...

def fill_gas_tank():
""" ."""
print("This car doesn't need a gas tank!")

- fill_gas_tank() ,
Python fill_gas_tank() Car
. ,
, .


-
. -
, - .

. , -
.
, ElectricCar ,
, -
.
Battery. Battery -
ElectricCar:
174 9

class Car():
...

class Battery():
""" ."""

def __init__(self, battery_size=70):


""" ."""
self.battery_size = battery_size
def describe_battery(self):
""" ."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")

class ElectricCar(Car):
""" , ."""
def __init__(self, make, model, year):
"""
-.
, .
"""
super().__init__(make, model, year)
self.battery = Battery()

my_tesla = ElectricCar('tesla', 'model s', 2016)

print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()

Battery,
. __init__() -
battery_size, self. , -
battery_size 70. describe_battery()
.
ElectricCar self.battery . -
Python Battery ( battery_
size , 70, )
self.battery. __init__();
ElectricCar
Battery.
my_
tesla. ,
battery:
my_tesla.battery.describe_battery()

Python my_tesla ,
battery describe_battery(),
Battery .
, :
2016 Tesla Model S
This car has a 70-kWh battery.
175

, ,
-
ElectricCar. Battery ,
:
class Car():
...

class Battery():
...

def get_range(self):
""" ."""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270

message = "This car can go approximately " + str(range)


message += " miles on a full charge."
print(message)

class ElectricCar(Car):
...

my_tesla = ElectricCar('tesla', 'model s', 2016)


print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

get_range() . -
70, get_range() 240 , 85 kWh
270 . .
, battery
.
:
2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.


, -
, .
?
, , get_range() Battery.
, , ,
get_range() ElectricCar. get_range()
- -
, , .
176 9

get_range() ,
(, car_model). get_range()
.
, , -
, .
Python, , . ,-
, ,
.
, ,
, . ,
, , ! , ,
.
,
.


9-6. : .
IceCreamStand, Restaurant 9-1 (. 165)
9-4 (. 169). ; ,
. flavors -
. , . IceCreamStand
.
9-7. : .
Admin, User 9-3 (. 165)
9-5 (. 170). privileges
, ,
. . show_privileges()
. Admin .
9-8. : Privileges.
privileges 9-7. show_privileges()
. Privileges Admin.
Admin .
9-9. :
electric_car.py . Battery upgrade_battery().
85,
.
, get_range(), get_range()
upgrade_battery(). , .



, .
Python -
. Python
.
177


, Car.
: car.py,
car.py,
Car. , Car
car.py , car.py , .
, , -
, my_car.py. car.py
Car:
car.py
""" ."""
class Car():
""" ."""

def __init__(self, make, model, year):


""" ."""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0

def get_descriptive_name(self):
""" ."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()

def read_odometer(self):
""" ."""
print("This car has " + str(self.odometer_reading) + " miles on it.")

def update_odometer(self, mileage):


"""
.
.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")

def increment_odometer(self, miles):


""" ."""
self.odometer_reading += miles


.
.
my_car.py.
Car :
my_car.py
from car import Car
178 9

my_new_car = Car('audi', 'a4', 2016)


print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

import Python car -


Car. Car ,
. ,
:
2016 Audi A4
This car has 23 miles on it.

. -
, ,
Car. ,
,
.
; , ,

.


, -
- . Battery ElectricCar
,
car.py:

car.py
""" ."""

class Car():
...

class Battery():
""" ."""
def __init__(self, battery_size=60):
""" ."""
self.battery_size = battery_size
def describe_battery(self):
""" ."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")

def get_range(self):
""" ."""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
179

message = "This car can go approximately " + str(range)


message += " miles on a full charge."
print(message)

class ElectricCar(Car):
""" , ."""
def __init__(self, make, model, year):
"""
-.
, .
"""
super().__init__(make, model, year)
self.battery = Battery()

my_electric_car.py,
ElectricCar :
my_electric_car.py
from car import ElectricCar

my_tesla = ElectricCar('tesla', 'model s', 2016)

print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

, ,
:
2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.


, .
,
, Car ElectricCar:
my_cars.py
from car import Car, ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2016)


print(my_beetle.get_descriptive_name())

my_tesla = ElectricCar('tesla', 'roadster', 2016)


print(my_tesla.get_descriptive_name())

, -
. ,
, .
180 9

Volkswagen Beetle -
Tesla Roadster :
2016 Volkswagen Beetle
2016 Tesla Roadster


, -
. ,
. , , -
, , .
my_cars.py
import car

my_beetle = car.Car('volkswagen', 'beetle', 2016)


print(my_beetle.get_descriptive_name())

my_tesla = car.ElectricCar('tesla', 'roadster', 2016)


print(my_tesla.get_descriptive_name())

car , -
_. _.
Volkswagen Beetle,
Tesla Roadster.


:
from _ import *

. ,
import -
, ,
, .
. , -
, .
? , -
, .
, ,
_.
_.
, , .
,
.
181


,

. ,
. -
.
, Car , ElectricCar Battery
. electric_car.py (
electric_car.py , ) Battery
ElectricCar:
electric_car.py
""" ."""
from car import Car

class Battery():
...

class ElectricCar(Car):
...

ElectricCar - Car, Car


. ,
ElectricCar . -
Car, Car:
car.py
""" ."""

class Car():
...


, :
my_cars.py
from car import Car
from electric_car import ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2016)


print(my_beetle.get_descriptive_name())

my_tesla = ElectricCar('tesla', 'roadster', 2016)


print(my_tesla.get_descriptive_name())

Car , ElectricCar -
. . ,
:
2016 Volkswagen Beetle
2016 Tesla Roadster
182 9


, Python
. ,
, -
.
. -
, , -
.
,
. , ,
.


9-10. Restaurant: Restaurant
. , Restaurant.
Restaurant Restaurant, ,
import .
9-11. Admin: 9-8 (.176).
User, Privileges Admin . , -
Admin show_privileges(), , -
.
9-12. : User , Privileges
Admin . Admin
show_privileges(), , .

Python
Python ,
Python. ,
, ,
.
, import .
OrderedDict collections.
, ,
.
, ,
OrderedDict collections.
OrderedDict , , ,
.
favorite_languages.py 6.
, :
favorite_languages.py
from collections import OrderedDict
favorite_languages = OrderedDict()
Python 183

favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'
for name, language in favorite_languages.items():
print(name.title() + "'s favorite language is " +
language.title() + ".")

OrderedDict collections -
. OrderedDict,
favorite_languages. ;
OrderedDict() favorite_
languages. .
favorite_languages
:
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.

,
( ) (
). ,
,
, .
, .

.
II,
.


9-13. OrderedDict Rewrite: 6-4 (. 113),
.
OrderedDict ,
.
9-14. : random -
. randint() . -
1 6:
from random import randint
x = randint(1, 6)
Die sides, -
6. roll_die() 1
. , 6- , 10 .
10- 20- . 10 .
9-15. : Python -
Python Module of the Week. http://pymotw.com/ -
. , ,
collections random.
184 9


, -
, .
:
, .
-
.
, -
. ,
, ,
.

.
,
. ,
.

, , import -
. import ,
. import
, ,
.

, . -

. , __init__()

. ,
-

.
,
, , -
. Python
, OrderedDict collections. ,

Python.
10 , -
.
Python, -
.
10

,
;
, .
, -
.
,
. -
,
, Python.
json, ,
.
.
, . -
, ,
, . -
,
, , .
-
- , -
. ,
, , .


.
, - , -
. ,
,
, , -
. , -
,
.
.
.
186 10


.
30 , 10 :
pi_digits.txt
3.1415926535
8979323846
2643383279

,
pi_digits.txt, https://
www.nostarch.com/pythoncrashcourse/. ,
.
,
:
file_reader.py
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)

.
open().
, . open()
: . Python
, . -
file_reader.py, Python pi_digits.txt
, file_reader.py. open() ,
. open('pi_digits.txt') -
, pi_digits.txt. Python
file_object, .
with ,
. : open(),
close(). open()
close(); - close() -
, . , -
.
close() ,
( ) , .
, ,
Python . ,
, , Python
.
, pi_digits.txt,
read(), -

187

contents. contents
:
3.1415926535
8979323846
2643383279


. ? read() -
, . ,
rstrip() print:
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents.rstrip())

, rstrip() .
:
3.1415926535
8979323846
2643383279


open() , pi_digits.txt, Python
, ,
( .py).
( , -
) -
. , python_work; -
python_work text_files ,
. text_files python_work,
open() text_files , Python
python_work ; -
text_files. ,
, ,
Python .
text_files python_work, text_files
. -
Python , ,
. Linux OS X -
:
with open('text_files/_.txt') as file_object:
, .txt text_files; -
, text_files python_work ( ).
Windows (/) (\):
with open('text_files\_.txt') as file_object:
188 10

-
, .
, .
, text_files python_work,
(, other_files), open() 'text_files/
filename.txt' , Python
python_work. Python, , -
.
,
, open(). Linux OS X
:
file_path = '/home/ehmatthes/other_files/text_files/_.txt'
with open(file_path) as file_object:
Windows :
file_path = 'C:\Users\ehmatthes\other_files\text_files\_.txt'
with open(file_path) as file_object:

-
.
, ( text_files
).

Windows .
Windows, ,
.


. -
, -
,
,
. , ,
.

for:
file_reader.py
filename = 'pi_digits.txt'

with open(filename) as file_object:


for line in file_object:
print(line)

, , -
filename. :
189

filename ( , -
Python, ), 'pi_digits.txt'
, . open()
, ,
file_object . with, Python
.
for .
:
3.1415926535

8979323846

2643383279

- , -
. print
,
: ,
print. rstrip() print -
:
filename = 'pi_digits.txt'

with open(filename) as file_object:


for line in file_object:
print(line.rstrip())

:
3.1415926535
8979323846
2643383279


with , open(),
with. ,
with,
.

.
pi_digits.txt with,
:
filename = 'pi_digits.txt'

with open(filename) as file_object:


lines = file_object.readlines()
190 10

for line in lines:


print(line.rstrip())

readlines()
. lines,
with. for
lines. lines
, .


,
, .
:
pi_string.py
filename = 'pi_digits.txt'

with open(filename) as file_object:


lines = file_object.readlines()

pi_string = ''
for line in lines:
pi_string += line.rstrip()

print(pi_string)
print(len(pi_string))


, . -
pi_string . ,
pi_string ,
. :
3.1415926535 8979323846 2643383279
36

pi_string ,
. , strip()
rstrip():
filename = 'pi_30_digits.txt'

with open(filename) as file_object:


lines = file_object.readlines()

pi_string = ''
for line in lines:
pi_string += line.strip()

print(pi_string)
print(len(pi_string))
191

, 30 .
32 ,
3 :
3.141592653589793238462643383279
32


, Python .
-
, int()
float().

:
,
,
. ,
1000000 ( 30), ,
.
. 50 ,
, :
pi_string.py
filename = 'pi_million_digits.txt'

with open(filename) as file_object:


lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()

print(pi_string[:52] + "...")
print(len(pi_string))

,
1000000 :
3.14159265358979323846264338327950288419716939937510...
1000002

Python ,
.
.

( , ) -
https://www.nostarch.com/pythoncrashcourse/.
192 10


,
? ,
.
,
pi_string:
filename = 'pi_million_digits.txt'

with open(filename) as file_object:


lines = file_object.readlines()

pi_string = ''
for line in lines:
pi_string += line.rstrip()

birthday = input("Enter your birthday, in the form mmddyy: ")


if birthday in pi_string:
print("Your birthday appears in the first million digits of pi!")
else:
print("Your birthday does not appear in the first million digits of pi.")

,
pi_string. :
Enter your birthdate, in the form mmddyy: 120372
Your birthday appears in the first million digits of pi!

, !
, ,
.


10-1. Python:
Python. : In Python
you can learning_python.txt ,
. , :
,
with.
10-2. C: replace()
. dog cat:
>>> message = "I really like dogs."

>>> message.replace('dog', 'cat')

'I really like cats.'


learning_python.txt
Python , C.
.
193


. ,
, -
.
.
, -
.


, open() ,
Python, .
, ,
( ):
write_message.py
filename = 'programming.txt'

with open(filename, 'w') as file_object:


file_object.write("I love programming.")
open() . ,
, . 'w'
Python, .
('r'), ('w'), ('a') , -
, ('r+'). ,
Python .
, , , open() -
. , ('w'):
, Python
.
write() .
, , programming.txt,
:
programming.txt
I love programming.

-
. , , /
..

Python . -
,
str().
194 10


write() .
,
, , :
filename = 'programming.txt'

with open(filename, 'w') as file_object:


file_object.write("I love programming.")
file_object.write("I love creating new games.")

programming.txt, , :
I love programming.I love creating new games.
write(),
:
filename = 'programming.txt'

with open(filename, 'w') as file_object:


file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")

:
I love programming.
I love creating new games.

, -
, .


,
, . -
Python .
, , .
, Python .
write_message.py
programming.txt :

write_message.py
filename = 'programming.txt'

with open(filename, 'a') as file_object:


file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")

'a'
( ).
, programming.txt:
195

programming.txt
I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.


10-3. : , .
guest.txt.
10-4. : while,
. -
guest_book.txt. ,
.
10-5. : while, , -
. ,
, .

, ,
Python , .
Python , ,
. , -
,
.
try-except. try-except
Python , , -
. try-except
, - .
,
.

ZeroDivisionError
, Python . -
, , , Python
:
division.py
print(5/0)

, :
Traceback (most recent call last):
File "division.py", line 1, in <module>
print(5/0)
ZeroDivisionError: division by zero
196 10

, ZeroDivisionError,
. , Python -
. Python
.
; Python,
.
.

try-except
, ,
try-except .
Python , , ,
.
try-except ZeroDivisionError:
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")

print(5/0), , try. -
try , Python except.
try , Python except
.
try ZeroDivisionError,
Python except , -
.
:
You can't divide by zero!

try-except ,
, Python, .
-
.



,
.
, . -
,
.
, :
197

division.py
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")

while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
answer = int(first_number) / int(second_number)
print(answer)

first_number , ,
q ,
second_number .
answer . ,
:
Give me two numbers, and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0
Traceback (most recent call last):
File "division.py", line 9, in <module>
answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero

, , ,
. ,

, . ,
.
,
.

else
,
, try-except. ,
; , try-except.
else. ,
try, else:
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")

while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
198 10

break
second_number = input("Second number: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)

try ,
, . ,
try, else. ,
, else -
.
except Python,
ZeroDivisionError . try
, 0, ,
, .
, :
Give me two numbers, and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0
You can't divide by 0!

First number: 5
Second number: 2
2.5

First number: q

try-except-else : Python try.


try ,
.
, try ; else.
except Python, , try -
. ,
,
.
.

FileNotFoundError

. , , ,
, .
try-except.
199

. -
,
alice.txt alice.py:
alice.py
filename = 'alice.txt'

with open(filename) as f_obj:


contents = f_obj.read()

, Python
:
Traceback (most recent call last):
File "alice.py", line 3, in <module>
with open(filename) as f_obj:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'

FileNotFoundError:
, Python .
open() , , , try -
open():
filename = 'alice.txt'

try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file " + filename + " does not exist."
print(msg)

try FileNotFoundError, -
Python except .
,
:
Sorry, the file alice.txt does not exist.

, , -
.
,
.


, .
, ,
. , ,
(http://gutenberg.org/). -
200 10

, ; -
,
.

. split(),
. split() , -
:
>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']

split() ,
, .
, (,
). -
split() , ,
:
filename = 'alice.txt'

try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file " + filename + " does not exist."
print(msg)
else:
# .
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) +
" words.")

alice.txt , try
.
contents, -
split() .
len(), -
.
, .
else,
try. ,
alice.txt:
The file alice.txt has about 29461 words.

,
, ,
.
201


.
count_words(). -
:
word_count.py
def count_words(filename):
""" ."""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file " + filename + " does not exist."
print(msg)
else:
# .
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) +
" words.")

filename = 'alice.txt'
count_words(filename)

. -
count_words(). ,
.
,
. -
, -
count_words(). ,
,
. siddhartha.txt
word_count.py, ,
:
def count_words(filename):
...

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']


for filename in filenames:
count_words(filename)

siddhartha.txt :
The file alice.txt has about 29461 words.
Sorry, the file siddhartha.txt does not exist.
The file moby_dick.txt has about 215136 words.
The file little_women.txt has about 189079 words.
202 10

try-except :
-
, , . -
FileNotFoundError, -
siddhartha.txt, ,
;
.


, -
.
.
, .
try , , except -
Python .
Python pass, :
def count_words(filename):
""" ."""
try:
...
except FileNotFoundError:
pass
else:
...

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']


for filename in filenames:
count_words(filename)

pass .
FileNotFoundError
except, . -
, .
,
, - :
The file alice.txt has about 29461 words.
The file moby_dick.txt has about 215136 words.
The file little_women.txt has about 189079 words.

pass . ,
-
, , , - . ,

missing_files.txt. ,
.
203

?
, ,
?
, , , -
, ,
. - , ,
? , -
- .
. Python
,
.
, -
(, ). ,
( ,
, ), -
. ,

.


10-6. : : -
. int
TypeError. , ,
. TypeError, -
, .
: , .
10-7. : 10-6 while,
, .
10-8. : cats.txt dogs.txt.
. ,
.
try-except FileNotFoundError
.
; , except , .
10-9. : except 10-8 ,
, .
10-10. : (http://gutenberg.org/)
. -
.
-
count(). , row
:
>>> line = "Row, row, row your boat"
>>> line.count('row')
2
>>> line.lower().count('row')
3
204 10

: lower() -
.
, -
the .


. -
,
. , -
, , (,
). ,
.
json.
json Python -
. json
Python.
, JSON Python,
, -
. ,
.

JSON (JavaScript Object Notation) JavaScript. ,


, Python.

json.dump() json.load()
,
.
json.dump(), json.load().
json.dump() : -
, . json.dump()
:
number_writer.py
import json

numbers = [2, 3, 5, 7, 11, 13]

filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)

json .
.
.json, , -
205

JSON. , json -
. json.dump()
numbers numbers.json.
, numbers.json
. , Python:
[2, 3, 5, 7, 11, 13]

, json.load()
:
number_reader.py
import json

filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)

print(numbers)

,
. , Python
. json.load() -
numbers.json;
numbers.
, . , ,
number_writer.py:
[2, 3, 5, 7, 11, 13]

json -
.

,
json -
, , -
.

.
:
remember_me.py
import json
username = input("What is your name? ")

filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username +
"!")
206 10

. -
json.dump(),
; . -
, :
What is your name? Eric
We'll remember you when you come back, Eric!

,
:
greet_user.py
import json

filename = 'username.json'

with open(filename) as f_obj:


username = json.load(f_obj)
print("Welcome back, " + username + "!")

json.load() username.json -
username. ,
:
Welcome back, Eric!

. -
remember_me.py, -
, ; , try,
. username.json ,
except username.json :
remember_me.py
import json

# , .
# .
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
username = input("What is your name? ")
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")
else:
print("Welcome back, " + username + "!")

; -
.
username.json. , -
, , else.
207

, username.json ,
FileNotFoundError . Python except,
. json.dump()
.
, -
.
:
What is your name? Eric
We'll remember you when you come back, Eric!

, :
Welcome back, Eric!

: , , -
, , -
. (
). ,
.
remember_me.py
. remember_me.py
, -
greet_user():
remember_me.py
import json

def greet_user():
""" ."""
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
username = input("What is your name? ")
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")
else:
print("Welcome back, " + username + "!")

greet_user()

, -
. ,
greet_user()
, , ,
.
208 10

greet_user(), .

:
import json

def get_stored_username():
""" , ."""
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username
def greet_user():
""" ."""
username = get_stored_username()
if username:
print("Welcome back, " + username + "!")
else:
username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")

greet_user()

get_stored_username() ,
.
, . username.json ,
None . :
, None.
.
, ;
.
greet_user() . -
, ,
:
import json

def get_stored_username():
""" , ."""
...

def get_new_username():
""" ."""
username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
return username
209

def greet_user():
""" ."""
username = get_stored_username()
if username:
print("Welcome back, " + username + "!")
else:
username = get_new_username()
print("We'll remember you when you come back, " + username + "!")

greet_user()

remember_me.py ,
. greet_user(), -
: , . -
get_stored_username(),
( ). , greet_user()
get_new_username(), -
.
,
.


10-11. : , -
. json.dump() .
, :
! _____.
10-12. : 10-11
. , , -
. ,
, .
10-13. : remember_me.py , -
, . -
, ,
.
greet_user(), ,
. , get_new_
username() .

. ,
.
,
, .
Python -
,
.
11 . -
, , -
, .
11

.
, , , -
, .
, , -
.
,
. ,
,
.
Python unittest.
, , ,
-
. ,
.


, .
, -
:
name_function.py
def get_formatted_name(first, last):
""" ."""
full_name = first + ' ' + last
return full_name.title()

get_formatted_name() , -
,
. , get_
formatted_name() , ,
. names.py
:
names.py
from name_function import get_formatted_name
211

print("Enter 'q' at any time to quit.")


while True:
first = input("\nPlease give me a first name: ")
if first == 'q':
break
last = input("Please give me a last name: ")
if last == 'q':
break

formatted_name = get_formatted_name(first, last)


print("\tNeatly formatted name: " + formatted_name + '.')

g e t _ f o r m a t t e d _ n a m e ( )
name_function.py .
, :
Enter 'q' at any time to quit.

Please give me a first name: janis


Please give me a last name: joplin
Neatly formatted name: Janis Joplin.

Please give me a first name: bob


Please give me a last name: dylan
Neatly formatted name: Bob Dylan.

Please give me a first name: q

, . ,
get_formatted_name(),
. ,
, . -
, names.py
(, Janis Joplin) get_formatted_name(),
. , Python
. -
get_formatted_name() ,
, .


, ,
,
. , -
unittest , .
, unittest.TestCase,
.
, , -
get_formatted_name() :
212 11

test_name_function.py
import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
""" 'name_function.py'."""

def test_first_last_name(self):
""" 'Janis Joplin' ?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')

unittest.main()

unittest get_formatted_name().
NamesTestCase,
get_formatted_name(). ,
, , , -
Test. unittest.
TestCase, Python , .
NamesTestCase ,
get_formatted_name() ,
. test_first_last_name(). ,
test_,
test_name_function.py. -
, .
get_formatted_name() 'janis' 'joplin',
formatted_name .
unittest:
assert. assert ,
, . ,
get_formatted_name() -
, formatted_name Janis
Joplin. , assertEqual()
unittest formatted_name 'Janis Joplin'.

self.assertEqual(formatted_name, 'Janis Joplin')


: formatted_name 'Janis Joplin'.
, , . ,
!
unittest.main() Python .
test_name_function.py :
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
213

, . -
, Python
0,001. , OK ,
.
, get_formatted_name()
, ,
. get_formatted_name() -
. , ,
.


? get_formatted_name(),
, ,
.
get_formatted_name()
:
name_function.py
def get_formatted_name(first, middle, last):
""" ."""
full_name = first + ' ' + middle + ' ' + last
return full_name.title()

, -
, .
test_name_function.py :
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_name_function.py", line 8, in test_first_last_name
formatted_name = get_formatted_name('janis', 'joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'
----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

,
, . E ,
, .
, test_first_last_name() NamesTestCase .
,
.
, , get_formatted_name('janis',
'joplin') - .
214 11

, . , -
,
.
, ;
, .


, ? ,
, , ,
. , , ,
, . , -
, , .
get_formatted_name()
: . : ,
.
get_formatted_name(). -
.
,
. get_formatted_name(),
, .
, .
, middle

. if,
, :
name_function.py
def get_formatted_name(first, last, middle=''):
""" ."""
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()

get_formatted_name() middle .
(if middle:), ,
. -
. .
, ,
test_name_function.py:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
215

. ; , -

. ,
, .


, get_formatted_name() , -
.
NamesTestCase :
import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
""" 'name_function.py'."""

def test_first_last_name(self):
""" , 'Janis Joplin'?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')

def test_first_last_middle_name(self):
""" , 'Wolfgang Amadeus Mozart'?"""
formatted_name = get_formatted_name(
'wolfgang', 'mozart', 'amadeus')
self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

unittest.main()

test_first_last_middle_name().
test_,
test_name_function.py. , ,
get_formatted_name() .
, .
TestCase: , -
, Python
, .
, get_formatted_name() c
, assertEqual() ,
. test_
name_function.py :
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

! , -
, Janis Joplin, ,
216 11

, Wolfgang Amadeus
Mozart.


11-1. , : , :
. -
, , Santiago, Chile. city_
functions.py.
test_cities.py (
unittest ). test_city_country()
, , santiago chile, -
. test_cities.py , test_city_country() -
.
11-2. : ,
.
Santiago, Chile population 5000000. test_cities.py.
, test_city_country() .
, .
test_cities.py , test_city_country() .
test_city_country_population(),
santiago, chile population=5000000. test_cities.py -
, .


. -
. -
, ,
, . ,
, , ,
-
.

assert
unittest.TestCase assert.
, , ,
. ,
,
; .
, , , Python
.
.11.1 assert.
, ,
True False -
. ,
217

unittest.TestCase;
.

11.1. assert, unittest


assertEqual(a, b) , a == b
assertNotEqual(a, b) , a != b
assertTrue(x) , x
assertFalse(x) , x
assertIn(, ) ,
assertNotIn(, ) ,


-
. ,
, .
:
survey.py
class AnonymousSurvey():
""" ."""

def __init__(self, question):


""" ."""
self.question = question
self.responses = []

def show_question(self):
""" ."""
print(question)

def store_response(self, new_response):


""" ."""
self.responses.append(new_response)

def show_results(self):
""" ."""
print("Survey results:")
for response in responses:
print('- ' + response)

, ,
.
, ,
. , -
. , -
, show_
218 11

question(), store_response()
show_results().
, AnonymousSurvey , -
, :
language_survey.py
from survey import AnonymousSurvey

# AnonymousSurvey.
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)

# .
my_survey.show_question()
print("Enter 'q' at any time to quit.\n")
while True:
response = input("Language: ")
if response == 'q':
break
my_survey.store_response(response)

# .
print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()

AnonymousSurvey -
. show_question() ,
. -
. ( q), show_results()
:
What language did you first learn to speak?
Enter 'q' at any time to quit.

Language: English
Language: Spanish
Language: English
Language: Mandarin
Language: q

Thank you to everyone who participated in the survey!


Survey results:
- English
- Spanish
- English
- Mandarin

. ,
AnonymousSurvey survey, -
. , .
,
, .
.
219


AnonymousSurvey. , ,
. -
, ,
.

AnonymousSurvey
, AnonymousSurvey.
, .
, assertIn() , -
:
test_survey.py
import unittest
from survey import AnonymousSurvey

class TestAnonmyousSurvey(unittest.TestCase):
""" AnonymousSurvey"""

def test_store_single_response(self):
""", ."""
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)
my_survey.store_response('English')

self.assertIn('English', my_survey.responses)

unittest.main()

unittest
AnonymousSurvey. TestAnonymousSurvey,
, unittest.TestCase . ,
.
test_store_single_response().
, -
, .
, .
my_survey "What language
did you first learn to speak?", (English) -
store_response(). ,
; , English
my_survey.responses .
test_survey.py :
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
220 11

, .
, . TestAnonymousSurvey
:
import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
""" AnonymousSurvey"""

def test_store_single_response(self):
""", ."""
...

def test_store_three_responses(self):
""", ."""
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)
responses = ['English', 'Spanish', 'Mandarin']
for response in responses:
my_survey.store_response(response)

for response in responses:


self.assertIn(response, my_survey.responses)

unittest.main()

test_store_three_responses().
, test_store_single_response().
, ,
store_response().
, ,
my_survey.responses .
test_survey.py, ( )
:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

. , -
unittest
.

setUp()
test_survey.py
AnonymousSurvey, . unittest.TestCase
221

setUp(), ,
. TestCase setUp(),
Python setUp() , -
test_. , setUp(),
.
setUp() AnonymousSurvey ,
test_store_single_response() test_store_
three_responses():
import unittest
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
""" AnonymousSurvey."""

def setUp(self):
"""
.
"""
question = "What language did you first learn to speak?"
self.my_survey = AnonymousSurvey(question)
self.responses = ['English', 'Spanish', 'Mandarin']

def test_store_single_response(self):
""", ."""
self.my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0], self.my_survey.responses)

def test_store_three_responses(self):
""", ."""
for response in self.responses:
self.my_survey.store_response(response)
for response in self.responses:
self.assertIn(response, self.my_survey.responses)

unittest.main()

setUp() : -
. self,
.
, .
test_store_single_response() , self.
responses self.responses[0] , test_store_single_
response() , self.
responses.
test_survey.py - .
AnonymousSurvey -
.
,
.
222 11

, , setUp()
. setUp(),
.
,
.

Python
. ;
, E, assert, F.

. -
, , -
.


11-3. : Employee, . __init__()
, ;
. give_raise(),
$5000 .
Employee. , test_give_
default_raise() test_give_custom_raise(). setUp(), -
Employee .
, .


unittest. , , unittest.
TestCase, -
. setUp()
,
.
, -
. ,
. -
, ,

. , -
, ,
. ,
, .
, -
.
,
. ,
223

, -
. , -
, ,
; , ,
, .
.
,
(
).
II.

! Python ,
, .
, I.
II ;
, .
, , .

Python
Alien Invasion ( 12, 13 14) Pygame
2D-, ,
. -
, 2D-
Pygame.


Data Visualization 15.
,
matplotlib Pygal. 16
-
. , 17
,
. -
.

-
Web Applications (18, 19 20) Django -
- - .
,
. ,
.
-
-. ,
, Django.
I.

12

! Pygame -
, Python ,
, . Pygame ,
,
, -
.
Pygame , -
.
, -
,
.
,
. -
, , .
-
. , -
. ,
, . -
, ,
.

Alien Invasion ; -
alien_invasion. import , -
.


, -
.
.
, . -
, ,
:
Pygame 227

, .
;
.
, .
. , ,
.
, . ,
.

,
. , -
. ,
.

Pygame
, Pygame.
Linux, OS X Microsoft Windows.
Python 3 Linux OS X,
Pygame pip ,
Python. pip
.
Python 2.7 Linux Windows,
Pygame pip .
Pygame Linux (. 229) Pygame Windows
(. 231).

pip , -
-.
https://www.nostarch.com/pythoncrashcourse/. , -
, , .

Python pip
Python pip ,
, . Python3
pip pip3.

pip Linux OS X
:
$ pip --version
pip 7.0.3 from /usr/local/lib/python3.5/dist-packages (python 3.5)
$
228 12

Python -
, Pygame Linux (.229)
Pygame OS X (. 230). ,
pip3 pip.
, pip (c. 228).
Python, , -
pip , Python 3.5 . -
pip , Pygame
Linux (. 229) Pygame OS X (.230). -
, pip3 pip.
Python, pip (c. 228).

pip Windows
:
$ python -m pip --version
pip 7.0.3 from C:\Python35\lib\site-packages (python 3.5)
$

Python,
, Pygame Windows
(.231). , pip3 -
pip. ,
pip (. 228).
Python, , -
pip , Python 3.5 . -
pip , Pygame
Windows (. 231). , pip3
pip. Python, -
pip.

pip
pip, https://bootstrap.pypa.io/get-pip.py. -
, . get-pip.py ,
get-pip.py.
get-pip.py , -
, pip
.

get-pip.py, https://pip.pypa.io/,
Installation , Install pip -
get-pip.py.
Pygame 229

pip Linux OS X
get-pip.py ,
:
$ sudo python get-pip.py

python3, sudo python3 get-


pip.py.
pip --version ( pip3 --version),
, pip .

pip Windows
get-pip.py, :
$ python get-pip.py
Python ,
, get-pip.py ,
python3 get-pip.py C:\Python35\python get-pip.py.
python -m pip --version,
, pip .

Pygame Linux
Python 2.7, Pygame -
. ,
Pygame :
$ sudo apt-get install python-pygame

;
:
$ python
>>> import pygame
>>>

, , Pygame
,
.231.
Python 3, : -
, Pygame, / Pygame.
, Pygame,
( , python3.5,
python3-dev python3.5-dev).
$ sudo apt-get install python3-dev mercurial
$ sudo apt-get install libsdl-image1.2-dev libsdl2-dev libsdl-ttf2.0-dev
230 12

,
Alien Invasion. Pygame
(, ), :
$ sudo apt-get install libsdl-mixer1.2-dev libportmidi-dev
$ sudo apt-get install libswscale-dev libsmpeg-dev libavformat-dev libavcode-dev
$ sudo apt-get install python-numpy

Pygame ( pip3, -
):
$ pip install --user hg+http://bitbucket.org/pygame/pygame

, .
Enter, . -
Pygame.
, -
Pygame:
$ python3
>>> import pygame
>>>

, -
. 231.

Pygame OS X
, Pygame,
Homebrew. , -
.
, Pygame,
:
$ brew install hg sdl sdl_image sdl_ttf

, Alien Invasion.

.
(, -
), :
$ brew install sdl_mixer portmidi

Pygame ( pip pip3,


Python 2.7):
$ pip3 install --user hg+http://bitbucket.org/pygame/pygame

, -
Pygame ( python python3,
Python 2.7):
231

$ python3
>>> import pygame
>>>

, -
.

Pygame Windows
Pygame Bitbucket.
Pygame Windows, https://
bitbucket.org/pygame/pygame/downloads/ Windows,
Python.
Bitbucket, http://www.lfd.uci.
edu/~gohlke/pythonlibs/#pygame.
, ,
.exe.
.whl, .
, ,
, pip :
> python -m pip install --user pygame-1.9.2a0-cp35-none-win32.whl


Pygame,
.
,
.

Pygame
Pygame. ,
Pygame:
alien_invasion.py
import sys

import pygame

def run_game():
# .
pygame.init()
screen = pygame.display.set_mode((1200, 800))
pygame.display.set_caption("Alien Invasion")

# .
232 12

while True:
# .
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()

# .
pygame.display.flip()
run_game()

sys pygame. pygame


, , sys
.
Alien Invasion run_game(). pygame.
init() , Pygame -
. pygame.display.set_mode()
screen, .
(1200, 800) , .
pygame.display.set_mode(), -
1200 800 . (
.)
screen (surface). Pygame -
, .
(, ) .
, display.set_mode(), .
-
.
while , ,
. , -
(,
). , -

.
for .
, Pygame,
pygame.event.get().
for. if
. ,
, pygame.QUIT,
sys.exit() .
pygame.display.flip() Pygame -
. while
,
. pygame.display.flip()
, -
;
.
233

run_game(),
.
, Pygame.


Pygame , .
:
alien_invasion.py
...
def run_game():
...
pygame.display.set_caption("Alien Invasion")

# .
bg_color = (230, 230, 230)

# .
while True:

# .
...
# .
screen.fill(bg_color)

# .
pygame.display.flip()

run_game()

bg_color.
, -
while.
Pygame RGB: ,
.
0 255. (255, 0, 0) , (0, 255,
0) (0, 0, 255) . RGB -
16 . (230, 230, 230) ,
, -
.
. screen.
fill(), : .

Settings
, ,
( ).
, settings;
234 12

Settings .
-
. ,
. ,
settings.py , -
.
Settings :
settings.py
class Settings():
""" Alien Invasion."""

def __init__(self):
""" ."""
#
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)

Settings ,
alien_invasion.py:
alien_invasion.py
...
import pygame

from settings import Settings

def run_game():
# pygame, settings .
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode(
(ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")

# .
while True:
...
# .
screen.fill(ai_settings.bg_color)

# .
pygame.display.flip()

run_game()

Settings ,
Settings ai_settings pygame.
init() . screen_width screen_
height ai_settings, ai_settings
.
235


, .
, ,
Pygame blit() .
, -
.
, http://pixabay.com/.
,
.bmp, Pygame -
. Pygame ,

. ( , , .jpg,
.png .gif, .bmp -
, Photoshop, GIMP Paint.)
.
, -
. ,
.
.
Alien Invasion ship.bmp (. 12.1), -
https://www.nostarch.com/pythoncrashcourse/.
, .
(alien_invasion) images.
ship.bmp images.

. 12.1. Alien Invasion


236 12

Ship
, .
ship, Ship.
.
ship.py
import pygame

class Ship():

def __init__(self, screen):


""" ."""
self.screen = screen

# .
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# .
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
def blitme(self):
""" ."""
self.screen.blit(self.image, self.rect)

pygame. __init__() Ship -


: self screen, .
pygame.image.load() .
, ; -
self.image.
, get_rect()
rect .
Pygame , -
,
. ,
.
,
.
rect x y , ,
, . ,
.
center,
centerx centery . top,
bottom, left right. -
x y ,
. ,
,
.
237

Pygame (0, 0) ,
. 1200 800
, (1200, 800).
. -
self.screen_rect ,
self.rect.centerx ( x ) centerx -
. self.rect.bottom ( y )
bottom . Pygame -
rect ,
, .
blitme(),
, self.rect.


alien_invasion.py, (
Ship) blitme() Ship:

alien_invasion.py
...
from settings import Settings
from ship import Ship

def run_game():
...
pygame.display.set_caption("Alien Invasion")

# .
ship = Ship(screen)

# Start the main loop for the game.


while True:
...
# .
screen.fill(ai_settings.bg_color)
ship.blitme()

# .
pygame.display.flip()

run_game()

Ship
( ship). while ,
.
, ship.blitme()
, .
alien_invasion.py , , -
(.12.2).
238 12

. 12.2.

: game_functions
-
.
.
game_functions , .
game_functions alien_invasion.py
alien_invasion.py .

check_events()
check_
events() . run_game()
.
(,
).
check_events() game_functions:
game_functions.py
import sys

import pygame

def check_events():
: game_functions 239

""" ."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()

sys pygame,
. , -
alien_invasion.py.
alien_invasion.py , game_
functions, check_events():

alien_invasion.py
import pygame

from settings import Settings


from ship import Ship
import game_functions as gf

def run_game():
...
# .
while True:
gf.check_events()

# .
...

sys , -
game_functions.
game_functions gf.

update_screen()
run_game() -
update_screen() game_functions.py:
game_functions.py
...

def check_events():
...

def update_screen(ai_settings, screen, ship):


""" ."""
# .
screen.fill(ai_settings.bg_color)
ship.blitme()

# .
pygame.display.flip()

update_screen() : ai_settings, screen


ship. while alien_invasion.py update_
screen():
240 12

alien_invasion.py
...
# .
while True:
gf.check_events()
gf.update_screen(ai_settings, screen, ship)

run_game()

while . -
run_game(), game_functions.
c , -
game_functions .
: ,
.
, ,
!


12-1. : Pygame .
12-2. : , ,
.bmp ( ). ,
,
( ).


. -
, . -
, .
.


, ,
Pygame . pygame.event.
get(), check_events() ,
.
KEYDOWN.
KEYDOWN , -
, . , -
rect.centerx
:
game_functions.py
def check_events(ship):
""" ."""
241

for event in pygame.event.get():


if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
# .
ship.rect.centerx += 1

check_events() ship,
. check_events()
elif KEYDOWN .
, (pygame.K_RIGHT),
event.key . ,
, ship.rect.centerx 1 .
check_events() alien_invasion.py ,
ship:
alien_invasion.py
# .
while True:
gf.check_events(ship)
gf.update_screen(ai_settings, screen, ship)

alien_invasion.py , , -
1 . ,
.
, .


, ,
. , ,
pygame.KEYUP; , -
KEYDOWN KEYUP -
moving_right.
moving_right False.
True, ,
False.
Ship ,
moving_right update() moving_
right. update() ,
True. ,
.
Ship:
ship.py
class Ship():
242 12

def __init__(self, screen):


...
# .
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom

#
self.moving_right = False

def update(self):
""" ."""
if self.moving_right:
self.rect.centerx += 1

def blitme(self):
...

self.moving_right __init__()
False . update(),
, True .
check_events(), moving_
right True, False:

game_functions.py
def check_events(ship):
""" ."""
for event in pygame.event.get():
...
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False

; -
moving_right
True. elif,
KEYUP. (K_RIGHT), moving_right
False.
while alien_invasion.py,
update() :
alien_invasion.py
# .
while True:
gf.check_events(ship)
ship.update()
gf.update_screen(ai_settings, screen, ship)

,
. , -
243


.
alien_invasion.py ,
, .


, , -
. Ship
check_events(). __init__()
update() Ship:
ship.py
def __init__(self, screen):
...
#
self.moving_right = False
self.moving_left = False

def update(self):
""" ."""
if self.moving_right:
self.rect.centerx += 1
if self.moving_left:
self.rect.centerx -= 1

__init__() self.moving_left. update()


if elif,
rect.centerx , .
. elif,
.
, -
.
check_events() :
game_functions.py
def check_events(ship):
""" ."""
for event in pygame.event.get():
...
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True

elif event.type == pygame.KEYUP:


if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
244 12

KEYDOWN K_LEFT, moving_left -


True. KEYUP K_LEFT, moving_left
False. elif,
.
, .
alien_invasion.py, ,
. , .
.
, .



while,
Settings ship_speed_factor.
. settings.py :
settings.py
class Settings():
""" Alien Invasion."""

def __init__(self):
...

ship_speed_factor 1.5. -
1,5 1.

. (, centerx)
, Ship :
ship.py
class Ship():
def __init__(self, ai_settings, screen):
""" ."""
self.screen = screen
self.ai_settings = ai_settings
...

#
...

# .
self.center = float(self.rect.centerx)

#
self.moving_right = False
self.moving_left = False
245

def update(self):
""" ."""
# center, rect.
if self.moving_right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left:
self.center -= self.ai_settings.ship_speed_factor

# rect self.center.
self.rect.centerx = self.center
def blitme(self):
...

__init__() ai_settings, -
. ai_settings
update() .
, -
, . rect
, rect .
self.center,
. float() -
self.rect.centerx
self.center.
update() self.center
, ai_settings.ship_speed_factor . -
self.center self.
rect.centerx, . self.rect.centerx
self.center,
.
ai_settings
Ship alien_invasion.py:

alien_invasion.py
...
def run_game():
...
# .
ship = Ship(ai_settings, screen)
...

ship_speed_factor, 1,
. ,
.


- ,
. , -
. update() Ship:
246 12

ship.py
def update(self):
""" ."""
# center, rect.
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor

# rect self.center
self.rect.centerx = self.center

self.center.
self.rect.right x
. , self.
screen_rect.right, , .
: x
0, , . -
, ,
self.center.
alien_invasion.py , -
.

check_events()
check_events() ,
check_events() : KEYDOWN
KEYUP:
game_functions.py
def check_keydown_events(event, ship):
""" ."""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True

def check_keyup_events(event, ship):


""" ."""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False

def check_events(ship):
""" ."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ship)
247

elif event.type == pygame.KEYUP:


check_keyup_events(event, ship)

: check_keydown_events() check_
keyup_events(). event ship.
check_events(),
. check_events() -
.


, -
bullet.py .
,
. ,
-
.

alien_invasion.py
alien_invasion.py , -
: ai_settings,
screen, ship
. alien_invasion.py while -
check_events(), ship.update() update_screen().
alien_invasion.py ,
Alien Invasion. settings.py, game_functions.py, ship.py -
, ( ) .

settings.py
settings.py Settings .
__init__(), ,
.

game_functions.py
game_functions.py ,
. check_events() , -
(, ), -

check_keydown_events() check_keyup_events().
. game_functions
update_screen(),
.
248 12

ship.py
ship.py Ship . __init__() ,
update() blitme()
. ship.bmp,
images.


12-3. : ,
. , ,
. , .
12-4. : Pygame, .
event.key pygame.KEYDOWN. -
, Pygame.

. , -
( ) .
, .


settings.py , -
Bullet. __init__():
settings.py
def __init__(self):
...
#
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60, 60, 60

- 3 15 -
. , .

Bullet
bullet.py Bullet.
bullet.py :

bullet.py
import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
249

""" , ."""

def __init__(self, ai_settings, screen, ship):


""" ."""
super(Bullet, self).__init__()
self.screen = screen

# (0,0) .
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top

# .
self.y = float(self.rect.y)

self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor

Bullet Sprite, pygame.sprite.


(sprite),
-
. , __init__()
ai_settings, screen ship, super()
Sprite.

super(Bullet, self).__init__() Python 2.7. Python 3


, super().__init__().
rect .
, -
pygame.Rect().
, .
(0, 0),
,
. ,
ai_settings.
centerx rect.centerx .
,

.
y
. -
self.color self.speed_factor.
bullet.py, update() draw_bullet():
bullet.py
def update(self):
""" ."""
250 12

# .
self.y -= self.speed_factor
# .
self.rect.y = self.y
def draw_bullet(self):
""" ."""
pygame.draw.rect(self.screen, self.color, self.rect)

update() . , -
, y; ,
, self.
speed_factor, self.y . self.y
self.rect.y . speed_factor
. x
, .
draw_bullet().
, , self.color .


Bullet ; -
, , -
. alien_invasion.py
, .
pygame.sprite.Group, -
,
.

:
alien_invasion.py
import pygame
from pygame.sprite import Group
...

def run_game():
...
# .
ship = Ship(ai_settings, screen)
# .
bullets = Group()

# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
bullets.update()
gf.update_screen(ai_settings, screen, ship, bullets)

run_game()
251

Group pygame.sprite. Group


bullets. while,
.

, ,
. , -
, while.
bullets check_events() update_screen(). check_
events() , update_screen()
.
update() update()
. bullets.update() bullet.update()
, bullets.


game_functions.py check_keydown_
events(), .
check_keyup_events() ,
. update_screen()
flip() .
game_functions.py:
game_functions.py
...
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
...
elif event.key == pygame.K_SPACE:
# bullets.
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
...

def check_events(ai_settings, screen, ship, bullets):


""" ."""
for event in pygame.event.get():
...
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
...

def update_screen(ai_settings, screen, ship, bullets):


...
# .
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
...
252 12

. 12.3.

bullets check_keydown_events() . -
, ( Bullet new_bullet), -
bullets add(); bullets.add(new_bullet)
bullets.
bullets
check_events() , check_keydown_
events().
bullets update_screen() ,
. bullets.sprites()
bullets. ,
bullets draw_bullet() .
alien_invasion.py ,
.
(. 12.3). , -
settings.py.


, ,
Pygame . -
; y .
,
.
253

, -
. ,
bottom 0, , -
:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
bullets.update()

# , .
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
print(len(bullets))

gf.update_screen(ai_settings, screen, ship, bullets)

for , -
. copy() for ,
bullets.
, .
, bullets . print,
, ;
, .
,
, 0 ,
.
, , print. -
, ,
, .


- , -
, .
Alien Invasion.
settings.py:
settings.py
#
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60, 60, 60
self.bullets_allowed = 3

. -
game_functions.py -
check_keydown_events():
254 12

game_functions.py
def check_keydown_events(event, ai_settings, screen, ship, bullets):
...
elif event.key == pygame.K_SPACE:
# bullets.
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)

bullets .
len(bullets) , . ,
, .
,
.

update_bullets()
, alien_invasion.py
,
game_functions.
update_bullets() game_functions.py:

game_functions.py
def update_bullets(bullets):
""" ."""
# .
bullets.update()

# , .
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)

update_bullets() alien_invasion.py;
bullets.
while alien_invasion.py :
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_screen(ai_settings, screen, ship, bullets)

,
, .
, , -
.
.
255

fire_bullet()
,
, elif check_keydown_events() :
game_functions.py
def check_keydown_events(event, ai_settings, screen, ship, bullets):
""" ."""
...
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)

def fire_bullet(ai_settings, screen, ship, bullets):


""" , ."""
# bullets.
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)

fire_bullet() ,
; fire_bullet() check_keydown_
events() .
alien_invasion.py ,
.


12-5. : ,
, .
, . , -
.

, -
, Pygame. ,
,
. -
. , ,
(, , ), , -
.
.
13 Alien Invasion . 13
,
!
13 , !

Alien Invasion . -
,
. ; ,
, . , -
, .
Pygame .
() ,
.
: ,

. , -
,
.
, ,
.


,
, ,
. :
, -
.
,
.

, . -
, , .
,
,
. ,
. ,
.
257

, , -
.
, -
.
, -
.
, -
. ,
,
,
, . -
Q:
game_functions.py
def check_keydown_events(event, ai_settings, screen, ship, bullets):
...
elif event.key == pygame.K_q:
sys.exit()

check_keydown_events() ,
Q. , Q
, -
Q . -
Q, .



. Alien,
Ship. -
.

. 13.1. ,
258 13 , !

. 13.1,
https://www.nostarch.com/pythoncrashcourse/.
, .
images.

Alien
Alien:
alien.py
import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
""", ."""

def __init__(self, ai_settings, screen):


""" ."""
super(Alien, self).__init__()
self.screen = screen
self.ai_settings = ai_settings

# rect.
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()

# .
self.rect.x = self.rect.width
self.rect.y = self.rect.height

# .
self.x = float(self.rect.x)

def blitme(self):
""" ."""
self.screen.blit(self.image, self.rect)

Ship ( -
). ,
, ,
, .

Alien
Alien alien_invasion.py:
alien_invasion.py
...
from ship import Ship
from alien import Alien
import game_functions as gf
259

def run_game():
...
# .
alien = Alien(ai_settings, screen)

# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_screen(ai_settings, screen, ship, alien, bullets)

run_game()

Alien Alien -
while.
, ;
update_screen(), alien.

. 13.2.

, blitme()
update_screen():
game_functions.py
def update_screen(ai_settings, screen, ship, alien, bullets):
...
260 13 , !

# .
for bullet in bullets:
bullet.draw_bullet()
ship.blitme()
alien.blitme()

# .
pygame.display.flip()

,
. .13.2 .
,
.


, ,
. -
;
.


, , -
. ai_
settings.screen_width,
. .
,
:
available_space_x = ai_settings.screen_width (2 * alien_width)

; -
. ,
, :
.
, :
number_aliens_x = available_space_x / (2 * alien_width)

:
, .
, . ,
, , .
.
261


, alien_invasion.py
aliens ,
game_functions.py :
alien_invasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
...
# , .
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()

# .
gf.create_fleet(ai_settings, screen, aliens)

# .
while True:
...
gf.update_screen(ai_settings, screen, ship, aliens,
bullets)

run_game()

alien_invasion.py,
Alien .
.
create_fleet() , ,
ai_settings, screen aliens. update_
screen(), .
update_screen():
game_functions.py
def update_screen(ai_settings, screen, ship, aliens, bullets):
...
ship.blitme()
aliens.draw(screen)

# .
pygame.display.flip()

draw() , Pygame
, rect. -
aliens.draw(screen)
.
262 13 , !


. create_
fleet(), game_functions.py.
Alien, import :
game_functions.py
...
from bullet import Bullet
from alien import Alien
...

def create_fleet(ai_settings, screen, aliens):


""" ."""
# .
# .

alien = Alien(ai_settings, screen)


alien_width = alien.rect.width
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))

# .
for alien_number in range(number_aliens_x):
# .
alien = Alien(ai_settings, screen)
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
aliens.add(alien)

.
,
. ,
aliens.
rect, alien_width,
rect. -
, .
:
int(), , -,
, , -, range()
. int() ,
. ( : -
, .)
0 .
, x
. .
2, ,
, , -
.
aliens.
263

. 13.3.

Alien Invasion, ,
(. 13.3).
, , -
, , ,
.. Space Invaders,
, .
,
.

create_fleet()
, create_fleet(),
, , , -
. create_fleet()
: get_number_aliens_x() create_alien():
game_functions.py
def get_number_aliens_x(ai_settings, alien_width):
""" ."""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
264 13 , !

def create_alien(ai_settings, screen, aliens, alien_number):


""" ."""
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
aliens.add(alien)

def create_fleet(ai_settings, screen, aliens):


""" ."""
# .
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)

# .
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number)
get_number_aliens_x() create_
fleet() . create_alien() , -
.
get_number_aliens_x(),
alien_width , create_alien(). -
create_alien().
.


,
( )
. , -
, (), ()
():
available_space_y = ai_settings.screen_height 3 * alien_height ship_height

,
.
, .
, (
, ,
, ):
number_rows = available_height_y / (2 * alien_height)

, :
game_functions.py
def get_number_rows(ai_settings, ship_height, alien_height):
""" , ."""
available_space_y = (ai_settings.screen_height -
265

(3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows

def create_alien(ai_settings, screen, aliens, alien_number, row_number):


...
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
aliens.add(alien)

def create_fleet(ai_settings, screen, ship, aliens):


...
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height,
alien.rect.height)

# .
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number,
row_number)

, , -
available_space_y number_rows get_number_rows() , -
get_number_aliens_x(). ,
79 ,
. int() ,
.
, :
. .
0 ; Python
number_rows .
, for -
. (
, , ,
.) create_alien()
, -
.
create_alien() . create_
alien() y .
, .
,
2, .
0, .
.
create_fleet() ship;
, create_fleet() alien_invasion.py
ship:
266 13 , !

. 13.4.

alien_invasion.py
# .
gf.create_fleet(ai_settings, screen, ship, aliens)

, (. 13.4).
.


13-1. : . .
13-2. -2: ,
. , -
:
from random import randint

random_number = randint(-10,10)
10 10.
13-1, .


, ;

267

. , ,
. -
.


,
update() alien.py, .
:
settings.py
def __init__(self):
...
#
self.alien_speed_factor = 1

update():
alien.py
def update(self):
""" ."""
self.x += self.ai_settings.alien_speed_factor
self.rect.x = self.x

,
alien_speed_factor. -
self.x, .
self.x .
while . -
:

alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_aliens(aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)

,
, - .
, update_aliens() game_functions.py:
game_functions.py
def update_aliens(aliens):
""" ."""
aliens.update()
268 13 , !

update() aliens, -
update() . Alien Invasion
, , .


, ,
. :
settings.py
#
self.alien_speed_factor = 1
self.fleet_drop_speed = 10
# fleet_direction = 1 ; -1 - .
self.fleet_direction = 1

fleet_drop_speed -
. -
, .
fleet_direction (-
, 'left' 'right'), , ,
if-elif .
, 1 1
. ( ,
x -
, .)


,
. update() , -
:
alien.py
def check_edges(self):
""" True, ."""
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= 0:
return True

def update(self):
""" ."""
self.x += (self.ai_settings.alien_speed_factor *
self.ai_settings.fleet_direction)
self.rect.x = self.x
269

check_edges() ,
. , ,
right rect right rect
. , , left
0 .
update() , -
; fleet_
direction. fleet_direction 1, alien_speed_factor
; fleet_direction
1, (
).


, -
. , game_functions.py
, ,
- .
check_fleet_edges() change_fleet_direction() ,
update_aliens():

game_functions.py
def check_fleet_edges(ai_settings, aliens):
""" ."""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break

def change_fleet_direction(ai_settings, aliens):


""" ."""
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1

def update_aliens(ai_settings, aliens):


"""
, ,
.
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()

check_fleet_edges() check_edges()
. check_edges() True, ,
, -
change_fleet_direction() .
change_fleet_direction()
fleet_drop_speed ;
270 13 , !

fleet_direction , -
1.
update_aliens()
check_fleet_edges() .
ai_settings, ai_settings update_
aliens():

alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)

, -
, . -
,
.


13-3. : .
.
13-4. : 13-3,
.


, , -
, , .
-
. , sprite.groupcollide()
.


, ,
.
.
sprite.groupcollide() rect -
rect -
, .
, ,
. (
14.)
271

update_bullets() :
game_functions.py
def update_bullets(aliens, bullets):
""" ."""
...
# .
# .
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

bullets,
aliens. ,
, groupcollide()
. True Pygame,
: . (
, ,
False, True. ,
, ,
.)
update_bullets() aliens:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(aliens, bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)

. 13.5. !
272 13 , !

Alien Invasion , , ,
. .13.5 .


, -
.
, , -
,
.

, . , ,
,
, .
Alien Invasion
, -
(. 13.6). bullet_width 300
, -
!
, -
. (
.)

. 13.6.

273


Alien Invasion :
, , .
, -
, aliens . , create_
fleet(). update_bullets(),
:
game_functions.py
def update_bullets(ai_settings, screen, ship, aliens, bullets):
...
# .
# .
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

if len(aliens) == 0:
# .
bullets.empty()
create_fleet(ai_settings, screen, ship, aliens)

, aliens. ,
empty(), -
. create_fleet()
.
update_bullets()
ai_settings, screen ship, update_bullets() alien_invasion.py -
:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)


, ,
. , Pygame
. -
bullet_speed_factor settings.py.
(, 3), :
settings.py
#
274 13 , !

self.bullet_speed_factor = 3
self.bul
...


. , -
.

update_bullets()
update_bullets(),
. :
game_functions.py
def update_bullets(ai_settings, screen, ship, aliens, bullets):
...
# .
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)

def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):


""" ."""
# , .
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

if len(aliens) == 0:
# .
bullets.empty()
create_fleet(ai_settings, screen, ship, aliens)

check_bullet_alien_collisions()

. , update_bullets()
.


13-5. : , -
.
. , , .
,
.


, ?
,
. , , ,
, .
, .
275


,
. -
-
:
game_functions.py
def update_aliens(ai_settings, ship, aliens):
"""
, ,
.
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()

# "-".
if pygame.sprite.spritecollideany(ship, aliens):
print("Ship hit!!!")

spritecollideany() : . -
, , -
.
aliens ,
.
, spritecollideany() None,
if . ,
, , if:
Ship hit!!! . (
: ,
. ,
,
. print -
.)
ship update_aliens():
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, ship, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)

Alien Invasion, -
Ship hit!!!.
alien_drop_speed (, 50
100), .
276 13 , !


,
. ship ,
;
. ( -
.)
GameStats
game_stats.py:

game_stats.py
class GameStats():
""" Alien Invasion."""

def __init__(self, ai_settings):


""" ."""
self.ai_settings = ai_settings
self.reset_stats()

def reset_stats(self):
""" , ."""
self.ships_left = self.ai_settings.ship_limit

Alien Invasion GameStats,


.
reset_stats()
__init__(). __init__(),
GameStats ,
reset_stats() .
ships_left, -
. settings.py
ship_limit:
settings.py
#
self.ship_speed_factor = 1.5
self.ship_limit = 3
alien_invasion.py -
GameStats:
alien_invasion.py
...
from settings import Settings
from game_stats import GameStats
...

def run_game():
...
pygame.display.set_caption("Alien Invasion")
277

# .
stats = GameStats(ai_settings)
...
# .
while True:
...
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, stats, screen, ship, aliens,
bullets)
...

GameStats , stats ,
stats, screen ship update_aliens() . -
,
, .
,
1, ,
. ( -
,
.)
ship_hit():
game_functions.py
import sys
from time import sleep

import pygame
...

def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):


""" ."""
# ships_left.
stats.ships_left -= 1

# .
aliens.empty()
bullets.empty()

# .
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()

# .
sleep(0.5)
def update_aliens(ai_settings, stats, screen, ship, aliens,
bullets):
...
# "-".
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, stats, screen, ship, aliens, bullets)

sleep() time,
. ship_hit()
278 13 , !

. ship_hit() -

1 , aliens bullets .

. ( center_ship() Ship.) ,
,
, , -
. sleep()
update_screen(), .
update_aliens()
stats, screen bullets ,
ship_hit().
center_ship(); ship.py:
ship.py
def center_ship(self):
""" ."""
self.center = self.screen_rect.centerx

, center ,
( screen_rect).

: . ship -
,
. , ,
ships_left.
, ,
. ,
, .


,
, .
, update_aliens():
game_functions.py
def check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets):
""", ."""
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# , .
ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
break

def update_aliens(ai_settings, stats, screen, ship, aliens, bullets):


...
279

# , .
check_aliens_bottom(ai_settings, stats, screen, ship, aliens,
bullets)

check_aliens_bottom() , , -
. , rect.
bottom rect.bottom . -
, ship_hit() .
, ,
ship_hit() .
check_aliens_bottom()
- .
,
, -
.


Alien Invasion - , . -
ships_left .
GameStats game_active,
:
game_stats.py
def __init__(self, settings):
....
# Alien Invasion .
self.game_active = True

ship_hit() , game_active False


:
game_functions.py
def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
""" ."""
if stats.ships_left > 0:
# ships_left.
stats.ships_left -= 1
...
# .
sleep(0.5)

else:
stats.game_active = False

ship_hit() .
if, ,
. , ,
. , game_active
False.
280 13 , !


alien_invasion.py , -
, ,
:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, ship, bullets)

if stats.game_active:
ship.update()
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, ship, aliens)

gf.update_screen(ai_settings, screen, ship, aliens, bullets)

check_events(),
. , -
, Q
. ,
, .
, ,
, .
-
.


13-6. : 13-5 (. 274) ,
. .


. , -
,
, update() .
(,
). , -
( -
).
.
Play,
, -
.
, .
!
14

Alien Invasion .
Play
. ,
, .
, ,

.

Play
Play,
, .
alien_invasion.py.
-
Play .
game_stats.py:
game_stats.py
def __init__(self, ai_settings):
""" ."""
self.ai_settings = ai_settings
self.reset_stats()

# .
self.game_active = False

def reset_stats(self):
...

, ,
Play.

Button
Pygame ,
Button .
282 14

.
Button; button.py:
button.py
import pygame.font

class Button():

def __init__(self, ai_settings, screen, msg):


""" ."""
self.screen = screen
self.screen_rect = screen.get_rect()

# .
self.width, self.height = 200, 50
self.button_color = (0, 255, 0)
self.text_color = (255, 255, 255)
self.font = pygame.font.SysFont(None, 48)

# rect .
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center

# .
self.prep_msg(msg)

pygame.font, Pygame
. __init__() self,
ai_settings screen, msg .
, button_color text_color ,
- ,
.
font . None
Pygame, -
, 48 .
, rect center -
.
Pygame .
prep_msg(). prep_msg() :
button.py
def prep_msg(self, msg):
""" msg ."""
self.msg_image = self.font.render(msg, True, self.text_color,
self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center

prep_msg() self , -
(msg). font.render() , -
msg, , msg_image .
Play 283

font.render() .
.
(True), .
( , Pygame .)
,
rect , center -
.
draw_button(), -
:
button.py
def draw_button(self):
# .
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)

screen.fill() .
screen.blit()
rect, . Button .


Button Play.
Play, alien_invasion.py:
alien_invasion.py
...
from game_stats import GameStats
from button import Button
...

def run_game():
...
pygame.display.set_caption("Alien Invasion")

# Play.
play_button = Button(ai_settings, screen, "Play")
...

# .
while True:
...
gf.update_screen(ai_settings, screen, stats, ship, aliens,
bullets,
play_button)

run_game()

Button play_button ,
play_button update_screen(),
.
284 14

update_screen(), Play
:
game_functions.py
def update_screen(ai_settings, screen, stats, ship, aliens, bullets,
play_button):
""" ."""
...

# Play , .
if not stats.game_active:
play_button.draw_button()

# .
pygame.display.flip()

Play ,
,
. Alien Invasion
Play (. 14.1).

. 14.1. Play ,


Play , game_
functions.py :

game_functions.py
def check_events(ai_settings, screen, stats, play_button, ship, bullets):
""" ."""
Play 285

for event in pygame.event.get():


if event.type == pygame.QUIT:
...
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(stats, play_button, mouse_x, mouse_y)

def check_play_button(stats, play_button, mouse_x, mouse_y):


""" Play."""
if play_button.rect.collidepoint(mouse_x, mouse_y):
stats.game_active = True

check_events() stats play_button.


stats game_active, play_
button , Play.
Pygame MOUSEBUTTONDOWN,
, ,
Play. pygame.mouse.get_pos(),
x y . -
check_play_button() , collidepoint()
, ,
Play . ,
game_active True, !
check_events() alien_invasion.py -
, stats play_button:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, stats, play_button, ship,
bullets)
...

. -
game_active False, Play
.


Play ,
, ,
, .
Play,
, ,
:
game_functions.py
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,
bullets, mouse_x, mouse_y):
286 14

""" Play."""
if play_button.rect.collidepoint(mouse_x, mouse_y):
# .
stats.reset_stats()
stats.game_active = True

# .
aliens.empty()
bullets.empty()

# .
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()

check_play_button(),
ai_settings, stats, ship, aliens bullets.
, , -
.
,
. game_active
True ( ),
aliens bullets , ,
.
check_events(), check_
play_button():

game_functions.py
def check_events(ai_settings, screen, stats, play_button, ship, aliens,
bullets):
""" ."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
...
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(ai_settings, screen, stats, play_
button, ship,
aliens, bullets, mouse_x, mouse_y)

check_events() aliens, -
check_play_button(). check_play_button()
.
check_events() alien_invasion.py,
aliens:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, stats, play_button, ship,
aliens, bullets)
...
Play 287


Play, , !

Play
Play :
, Play .
Play , !
, ,
game_active False:
game_functions.py
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,
bullets, mouse_x, mouse_y):
""" Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# .
...

button_clicked True False ; -


, Play,
. ,
, Play.
, , Play .


, ,
. ,
, :
game_functions.py
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,
bullets, mouse_x, mouse_y):
""" Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# .
pygame.mouse.set_visible(False)
...

set_visible() False Pygame ,


.
, -
Play . :
game_functions.py
def ship_hit(ai_settings, screen, stats, ship, aliens, bullets):
288 14

""" ."""
if stats.ships_left > 0:
...
else:
stats.game_active = False
pygame.mouse.set_visible(True)

,
, ship_hit().
,
, .


14-1. P: Alien Invasion -
, . ,
P. , check_play_
button() start_game(), check_
play_button() check_keydown_events().
14-2. : , -
. , -
-
. Play . ,
Play. .


, ,
, .
; -
, .


Settings -
: . ,
, , -
. __init__() settings.py :
settings.py
def __init__(self):
""" ."""
#
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)

#
self.ship_limit = 3

#
289

self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60, 60, 60
self.bullets_allowed = 3

#
self.fleet_drop_speed = 10

#
self.speedup_scale = 1.1

self.initialize_dynamic_settings()

, , - -
__init__(). speedup_scale,
; 2 ,
, 1
. , 1,1, -
, , . ,
initialize_dynamic_settings() ,
.
initialize_dynamic_settings() :
settings.py
def initialize_dynamic_settings(self):
""" , ."""
self.ship_speed_factor = 1.5
self.bullet_speed_factor = 3
self.alien_speed_factor = 1

# fleet_direction = 1 ; -1 - .
self.fleet_direction = 1

, . -
,
. fleet_direction,
.
, ,
, increase_
speed():

settings.py
def increase_speed(self):
""" ."""
self.ship_speed_factor *= self.speedup_scale
self.bullet_speed_factor *= self.speedup_scale
self.alien_speed_factor *= self.speedup_scale

, -
speedup_scale.
290 14

increase_speed() check_bullet_alien_
collisions() , -
:
game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):
...
if len(aliens) == 0:
# , .
bullets.empty()
ai_settings.increase_speed()
create_fleet(ai_settings, screen, ship, aliens)

ship_speed_factor, alien_speed_factor
bullet_speed_factor , !


, ,
, -
:
game_functions.py
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,
bullets, mouse_x, mouse_y):
""" Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# .
ai_settings.initialize_dynamic_settings()

# .
pygame.mouse.set_visible(False)
...

Alien Invasion . ,
, ,
. ,
settings.speedup_scale, , , -
. ,
. , -
, ,
.


14-3. : 14-2
(. 288). ,
Play .
291


; -
,
. ,
score GameStats:
game_stats.py
class GameStats():
...
def reset_stats(self):
""" , ."""
self.ships_left = self.ai_settings.ship_limit
self.score = 0

, score
reset_stats() __init__().


, Scoreboard.
, -
, .
; scoreboard.py:
scoreboard.py
import pygame.font
class Scoreboard():
""" ."""
def __init__(self, ai_settings, screen, stats):
""" ."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.stats = stats

# .
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
# .
self.prep_score()

Scoreboard ,
pygame.font. __init__() ai_settings, screen
stats, .
.
, prep_
score() , :

scoreboard.py
def prep_score(self):
""" ."""
292 14

score_str = str(self.stats.score)
self.score_image = self.font.render(score_str, True, self.
text_color,
self.ai_settings.bg_color)

# .
self.score_rect = self.score_image.get_rect()
self.score_rect.right = self.screen_rect.right - 20
self.score_rect.top = 20

prep_score() stats.score ;
render(), .
, render() .

.
, rect score_rect
20 .
20 .
show_score() -
:
scoreboard.py
def show_score(self):
""" ."""
self.screen.blit(self.score_image, self.score_rect)

, score_rect.

Scoreboard
, alien_invasion.py Scoreboard:
alien_invasion.py
...
from game_stats import GameStats
from scoreboard import Scoreboard
...
def run_game():
...
# GameStats Scoreboard.
stats = GameStats(ai_settings)
sb = Scoreboard(ai_settings, screen, stats)
...
# .
while True:
...
gf.update_screen(ai_settings, screen, stats, sb, ship,
aliens,
bullets, play_button)

run_game()
293

Scoreboard sb
stats . sb update_screen(),
.
update_screen() :
game_functions.py
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,
play_button):
...
# .
sb.show_score()

# Play , .
if not stats.game_active:
play_button.draw_button()

# .
pygame.display.flip()

sb , update_screen(), -
show_score() Play.
Alien Invasion ,
0. ( ,
, .)
.14.2 .

. 14.2.

!
294 14


,
stats.score ,
prep_score() . ,
:
settings.py
def initialize_dynamic_settings(self):
...

#
self.alien_points = 50

. -
,
initialize_dynamic_settings().
check_bullet_alien_
collisions():

game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
aliens, bullets):
""" ."""
# , .
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if collisions:
stats.score += ai_settings.alien_points
sb.prep_score()
...

check_bullet_alien_collisions() -
stats sb, .
Pygame collisions. ,
,
. prep_score() -
.
update_bullets(), -
:
game_functions.py
def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
""" ."""
...

check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,


aliens, bullets)

update_bullets() stats
sb. , check_bullet_alien_collisions() -
stats sb.
295

update_bullets() while:
alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, stats, play_button, ship,
aliens, bullets)
if stats.game_active:
ship.update()
gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens,
bullets)
...

update_bullets() stats sb.


!


, ,
. , -

,
. , -
.
check_bullet_alien_collisions() , -
, collisions.
, .
collisions , -
:
game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
aliens, bullets):
...
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points * len(aliens)
sb.prep_score()
...

collisions ,
collisions. , -
, .
, -
.
, 300 -
, ,
; .
296 14


,
.
, ,
:
settings.py
class Settings():
""" Alien Invasion."""

def __init__(self):
...
#
self.speedup_scale = 1.1
#
self.score_scale = 1.5
self.initialize_dynamic_settings()

def increase_speed(self):
""" ."""
self.ship_speed_factor *= self.speedup_scale
self.bullet_speed_factor *= self.speedup_scale
self.alien_speed_factor *= self.speedup_scale

self.alien_points = int(self.alien_points * self.score_


scale)

; -
score_scale . (1,1)
, , ,
(1,5).
.
, int().
, increase_speed()
Settings print:
settings.py
def increase_speed(self):
...
self.alien_points = int(self.alien_points * self.score_scale)
print(self.alien_points)

,
.


, ,
print;
.
297


, 10,
. ,
.
Scoreboard:
scoreboard.py
def prep_score(self):
""" ."""
rounded_score = int(round(self.stats.score, -1))
score_str = "{:,}".format(rounded_score)
self.score_image = self.font.render(score_str, True, self.text_color,
self.ai_settings.bg_color)
...

round() -
, .
, round() , ,
.. Python stats.score -
rounded_score.

Python 2.7 round() ,


int(), , .
Python3, int() .

. 14.3.
298 14

Python
,
1000000 1,000,000.
,
(.14.3).

, -
, .
GameStats:
game_stats.py
def __init__(self, ai_settings):
...
# .
self.high_score = 0

, high_
score __init__(), reset_stats().
Scoreboard .
__init__():

scoreboard.py
def __init__(self, ai_settings, screen, stats):
...
# .
self.prep_score()
self.prep_high_score()

,
prep_high_score():
scoreboard.py
def prep_high_score(self):
""" ."""
high_score = int(round(self.stats.high_score, -1))
high_score_str = "{:,}".format(high_score)
self.high_score_image = self.font.render(high_score_str,
True,
self.text_color, self.ai_settings.bg_color)

# .
self.high_score_rect = self.high_score_image.get_rect()
self.high_score_rect.centerx = self.screen_rect.centerx
self.high_score_rect.top = self.score_rect.top

.
, -
, top
.
299

show_score() , -
:
scoreboard.py
def show_score(self):
""" ."""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)

game_functions.py
check_high_score():

game_functions.py
def check_high_score(stats, sb):
""", ."""
if stats.score > stats.high_score:
stats.high_score = stats.score
sb.prep_high_score()

. 14.4.

check_high_score() , stats sb. stats


, sb
.
. ,
high_score prep_high_score()
.
check_high_score() -
check_bullet_alien_collisions():
300 14

game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
aliens, bullets):
...
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points * len(aliens)
sb.prep_score()
check_high_score(stats, sb)
...

Alien Invasion,
, , .
,
, . 14.4.


, GameStats -
.
, reset_stats():
game_stats.py
def reset_stats(self):
""" , ."""
self.ships_left = self.ai_settings.ship_limit
self.score = 0
self.level = 1

Scoreboard ( ),
prep_level() __init__():
scoreboard.py
def __init__(self, ai_settings, screen, stats):
...

# .
self.prep_score()
self.prep_high_score()
self.prep_level()

prep_level() :
scoreboard.py
def prep_level(self):
""" ."""
self.level_image = self.font.render(str(self.stats.level),
True,
self.text_color, self.ai_settings.bg_color)

# .
self.level_rect = self.level_image.get_rect()
301

self.level_rect.right = self.score_rect.right
self.level_rect.top = self.score_rect.bottom + 10

prep_level() , stats.
level , right
right . top 10
,
.
show_score() :
scoreboard.py
def show_score(self):
""" , ."""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
self.screen.blit(self.level_image, self.level_rect)

, .
stats.level check_
bullet_alien_collisions():
game_functions.py
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
aliens, bullets):
...
if len(aliens) == 0:
# , .
bullets.empty()
ai_settings.increase_speed()

# .
stats.level += 1
sb.prep_level()

create_fleet(ai_settings, screen, ship, aliens)

, stats.level
prep_level() .
,
, Play:
game_functions.py
def check_play_button(ai_settings, screen, stats, sb, play_button, ship,
aliens, bullets, mouse_x, mouse_y):
""" Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
...
# .
stats.reset_stats()
stats.game_active = True

# .
302 14

sb.prep_score()
sb.prep_high_score()
sb.prep_level()

# .
aliens.empty()
bullets.empty()

...

check_play_button() sb. -
, prep_score(),
prep_high_score() prep_level().
sb check_events(), Scoreboard
check_play_button():

game_functions.py
def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens,
bullets):
""" ."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
...
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(ai_settings, screen, stats, sb, play_
button,
ship, aliens, bullets, mouse_x, mouse_y)

check_events() sb ,
check_play_button() sb .
check_events() alien_invasion.py,
sb:

alien_invasion.py
# .
while True:
gf.check_events(ai_settings, screen, stats, sb, play_button, ship,
aliens, bullets)
...

(.14.5).

: -
, .. , ,
Alien Invasion. ,
font.render() Scoreboard.
303

. 14.5.


, , -
. -
,
. .
, Ship Sprite, -
:
ship.py
import pygame
from pygame.sprite import Sprite

class Ship(Sprite):

def __init__(self, ai_settings, screen):


""" ."""
super(Ship, self).__init__()
...

Sprite, Ship Sprite -


super() __init__() .
Scoreboard
. import __init__() :
scoreboard.py
import pygame.font
from pygame.sprite import Group
304 14

from ship import Ship

class Scoreboard():
""" ."""

def __init__(self, ai_settings, screen, stats):


...
self.prep_level()
self.prep_ships()
...

,
Group Ship. prep_ships() prep_level(). -
:
scoreboard.py
def prep_ships(self):
""" ."""
self.ships = Group()
for ship_number in range(self.stats.ships_left):
ship = Ship(self.ai_settings, self.screen)
ship.rect.x = 10 + ship_number * ship.rect.width
ship.rect.y = 10
self.ships.add(ship)

prep_ships() self.ships
.
, . ,
x ,
, 10 . y -
, 10
. ,
ships .
:
scoreboard.py
def show_score(self):
...
self.screen.blit(self.level_image, self.level_rect)
# .
self.ships.draw(self.screen)

draw() , Pygame
.
, , prep_
ships() . check_play_button()
game_functions.py:
game_functions.py
def check_play_button(ai_settings, screen, stats, sb, play_button, ship,
305

aliens, bullets, mouse_x, mouse_y):


""" Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
...
# .
sb.prep_score()
sb.prep_high_score()
sb.prep_level()
sb.prep_ships()
...

prep_ships() ,
:
game_functions.py
def update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets):
...
# "-".
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, screen, stats, sb, ship, aliens,
bullets)

# , .
check_aliens_bottom(ai_settings, screen, stats, sb, ship,
aliens, bullets)

def ship_hit(ai_settings, screen, stats, sb, ship, aliens,


bullets):
""" ."""
if stats.ships_left > 0:
# ships_left.
stats.ships_left -= 1

# .
sb.prep_ships()

# .
...

sb update_aliens() . -
sb ship_hit() check_aliens_bottom(),
Scoreboard .
ship_hit() sb . prep_ships()
ships_left ,
.
ship_hit() check_aliens_bottom(),
:
game_functions.py
def check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens,
bullets):
""", ."""
306 14

screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# , .
ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets)
break

check_aliens_bottom() sb, -
sb ship_hit().
sb update_aliens() alien_invasion.py:
alien_invasion.py
# .
while True:
...
if stats.game_active:
ship.update()
gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens,
bullets)
gf.update_aliens(ai_settings, screen, stats, sb, ship, aliens,
bullets)
...

. 14.6 , -
.

. 14.6. Alien Invasion


307


14-4. : ,
Alien Invasion. ,
sys.exit() GameStats.
14-5. : , , -
, . , -
check_bullet_alien_collisions(),
, start_new_level(). ,
__init__() Scoreboard, prep_images()
__init__(). prep_images() check_play_button()
start_game(), check_play_button().


, . -
, , -
.
14-6. Alien Invasion: Alien Invasion.
, , -
, (
). (, ) -
pygame.mixer.

, , -
.
,
. , -

.
2.

15


. (data mining), -

. ,
, .
.
, ,
.
, .
, . -
Python
( ) .
. ,
, .
Python , , -
.
Python -
, .
matplotlib,
. matplotlib
, , ..
, -
, .
Pygal,
, .
Pygal -
; ,
.
Pygal .

matplotlib
matplotlib, -
.
310 15

pip, Python
pip (.227).

Linux
Python, ,
matplotlib
:
$ sudo apt-get install python3-matplotlib

Python 2.7, :
$ sudo apt-get install python-matplotlib

Python,
, matplotlib:
$ sudo apt-get install python3.5-dev python3.5-tk tk-dev
$ sudo apt-get install libfreetype6-dev g++

pip matplotlib:
$ pip install --user matplotlib

OS X
Apple matplotlib Python. -
, ,
matplotlib. matplotlib
Homebrew Python,
:
$ pip install --user matplotlib

, pip3 pip.
, --user.

Windows
Windows Visual Studio. -
https://dev.windows.com/, (Downloads)
Visual Studio Community
Windows. .
matplotlib .
https://pypi.python.org/pypi/matplotlib/ -
.whl , Python. ,
32- Python 3.5, matplotlib-1.4.3-
cp35-none-win32.whl.
311

, Python,
http://www.lfd.uci.edu/~gohlke/pythonlibs/#matplotlib. -
, matplotlib.
.whl ,
. pip matplotlib:
> cd python_work
python_work> python -m pip install --user matplotlib-1.4.3-cp35-none-win32.whl

matplotlib
, -
. python python3
matplotlib:
$ python3
>>> import matplotlib
>>>

, , matplotlib
.

, .
, . , Python
.

matplotlib
,
matplotlib, http://matplotlib.org/. -
, , .


matplotlib,
.
1, 4, 9,
16 25.
matplotlib , , matplotlib
:
mpl_squares.py
import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]


plt.plot(squares)
plt.show()
312 15

pyplot plt, -
pyplot. ( -
, .) pyplot
.
plot(), -

. plt.show() matplotlib
(. 15.1). -
,
.

. 15.1. matplotlib


. 15.1 , ,
, . , matplotlib
.
,
:
mpl_squares.py
import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]


plt.plot(squares, linewidth=5)

# .
plt.title("Square Numbers", fontsize=24)
plt.xlabel("Value", fontsize=14)
313

plt.ylabel("Square of Value", fontsize=14)

# .
plt.tick_params(axis='both', labelsize=14)

plt.show()

linewidth , -
plot(). title() .
fontsize , ,
.
xlabel() ylabel() () -
, tick_params()
. , ,
(axes='both')
14 (labelsize=14).
.15.2, . -
, .

. 15.2.


, , ,
. : 4,0
25! .
plot() , ,
x 0,
1. -
, plot() , :
314 15

mpl_squares.py
import matplotlib.pyplot as plt

input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
plt.plot(input_values, squares, linewidth=5)

# .
...

plot() ,
, , -
. . 15.3 .

. 15.3.

plot() , -
.
,
.

scatter()
, -
, . ,
.
: , ,
, .
scatter().
scatter() (x, y) ,
:
315

scatter_squares.py
import matplotlib.pyplot as plt

plt.scatter(2, 4)
plt.show()

, .
, , , :
import matplotlib.pyplot as plt

plt.scatter(2, 4, s=200)

# .
plt.title("Square Numbers", fontsize=24)
plt.xlabel("Value", fontsize=14)
plt.ylabel("Square of Value", fontsize=14)

# .
plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()

; s ,
. scatter_squares.py
, (. 15.4).

. 15.4.

scatter()
, scatter()
x y:
316 15

scatter_squares.py
import matplotlib.pyplot as plt

x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]

plt.scatter(x_values, y_values, s=100)

# .
...

x_values , , y_values
. scatter() matplotlib
.
, (1, 1), (2, 4), (3, 9), (4, 16)
(5, 25); . 15.5.

. 15.5.


, .
,
Python, .
1000 :
scatter_squares.py
import matplotlib.pyplot as plt

x_values = list(range(1, 1001))


y_values = [x**2 for x in x_values]

plt.scatter(x_values, y_values, s=40)


317

# .
...

# .
w plt.axis([0, 1100, 0, 1100000])

plt.show()

x 1 1000 .
y, x (for x in x_values), -
(x**2) y_values.
( ) scatter() .
, ,
axis() .
axis() : x y.
x 0 1100, y 0
1100000. . 15.6 .

. 15.6. 1000 ,
5


matplotlib
.
.
.
, edgecolor='none' scatter():
plt.scatter(x_values, y_values, edgecolor='none', s=40)

scatter_squares.py , , -
.
318 15


, scatter() c -
:
plt.scatter(x_values, y_values, c='red', edgecolor='none', s=40)

RGB. -
, c
( , ) 0 1. ,
- :
plt.scatter(x_values, y_values, c=(0, 0, 0.8), edgecolor='none', s=40)

, 0, , , 1,
.


(colormap) , -
.
. -
, , .
pyplot .
, , pyplot
. -
y:
scatter_squares.py
import matplotlib.pyplot as plt

x_values = list(range(1001))
y_values = [x**2 for x in x_values]

plt.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues,


edgecolor='none', s=40)

# .
...

c y-values, pyplot,
, cmap .
y - ,
y - . -
.15.7.

, pyplot, http://matplotlib.org/; -
Examples, Color Examples
colormaps_reference.
319

. 15.7. Blues


, ,
plt.show() plt.savefig():
plt.savefig('squares_plot.png', bbox_inches='tight')
; -
scatter_squares.py. -
. ,
.


15-1. : , , . -
, 5000 .
15-2. : .


Python
, matplotlib
. (random walk) ,
, -
. ,
; .
:
, , . , -
,
. ,
320 15


. , ,
.

RandomWalk()
, RandomWalk, -
.
:
x y .
RandomWalk : __init__() fill_walk() -
. __init__():
random_walk.py
from random import choice

class RandomWalk():
""" ."""

def __init__(self, num_points=5000):


""" ."""
self.num_points = num_points

# (0, 0).
self.x_values = [0]
self.y_values = [0]

,
choice() . -
5000 ,
, ,
.
x y, (0,0).


fill_walk(), , -
. random_walk.py:
random_walk.py
def fill_walk(self):
""" ."""

# .
while len(self.x_values) < self.num_points:
# .
x_direction = choice([1, -1])
x_distance = choice([0, 1, 2, 3, 4])
x_step = x_direction * x_distance
321

y_direction = choice([1, -1])


y_distance = choice([0, 1, 2, 3, 4])
y_step = y_direction * y_distance

# .
if x_step == 0 and y_step == 0:
continue

# x y.
next_x = self.x_values[-1] + x_step
next_y = self.y_values[-1] + y_step

self.x_values.append(next_x)
self.y_values.append(next_y)

,
. Python,
: ?
? ?
?
choice([1, -1]) x_direction; 1
1 . choice([0,
1, 2, 3, 4]) (x_distance)
0 4. ( 0
y, .)
x y,
.
x_step , ,
. y_step , -
, . x_step y_step
0, , .
x , x_step -
, x_values , -
y. , x_values
y_values.


:
rw_visual.py
import matplotlib.pyplot as plt

from random_walk import RandomWalk

# .
rw = RandomWalk()
rw.fill_walk()
plt.scatter(rw.x_values, rw.y_values, s=15)
plt.show()
322 15

pyplot RandomWalk.
rw , fill_walk(). -
scatter() x y
.
. 15.8 5000 . ( -
matplotlib ,
rw_visual.py.)

. 15.8. 5000


;
, .

while:
rw_visual.py
import matplotlib.pyplot as plt

from random_walk import RandomWalk

# , .
while True:
# .
rw = RandomWalk()
rw.fill_walk()
plt.scatter(rw.x_values, rw.y_values, s=15)
plt.show()

keep_running = input("Make another walk? (y/n): ")


if keep_running == 'n':
break
323

,
matplotlib .
, ,
. y, , -
,
; .
, n.

Python 2.7, raw_input() input() .


, -

. ,
(, ,
). , (-
, ).
, , -
.


, -
, .
, -
c . ,
1 5000:
rw_visual.py
...
while True:
# .
rw = RandomWalk()
rw.fill_walk()

point_numbers = list(range(rw.num_points))
plt.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues,
edgecolor='none', s=15)
plt.show()

keep_running = input("Make another walk? (y/n): ")


...

range() ,
.
point_numbers,
324 15

. point_numbers c,
Blues edgecolor=none
. -
- - (. 15.9).

. 15.9. ,
Blues


, , ,
. -
, .
,
:
rw_visual.py
...
while True:
...
plt.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues,
edgecolor='none', s=15)

# .
plt.scatter(0, 0, c='green', edgecolors='none', s=100)
plt.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none',
s=100)

plt.show()
...
325

, (0, 0) -
(s=100) . -
x y 100.
plt.show(),
.
,
. ( , -
, .)


, .
:
rw_visual.py
...
while True:
...
plt.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none',
s=100)

# .
plt.axes().get_xaxis().set_visible(False)
plt.axes().get_yaxis().set_visible(False)

plt.show()
...

plt.axes() False.
.
rw_visual.py; .


, .
num_points RandomWalk -
:
rw_visual.py
...
while True:
# .
rw = RandomWalk(50000)
rw.fill_walk()

# .
point_numbers = list(range(rw.num_points))
plt.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues,
edgecolor='none', s=1)
...
326 15

50000 (
), s=1.
.15.10, .
!
, -
,
.

. 15.10. 50000


,
. ,
matplotlib:
rw_visual.py
...
while True:
# Make a random walk, and plot the points.
rw = RandomWalk()
rw.fill_walk()

# .
plt.figure(figsize=(10, 6))
...

figure() , ,
. figsize
.
Pygal 327

Python , 80 ;
, .
, , figure()
dpi , -
:
plt.figure(dpi=128, figsize=(10, 6))


15-3. : rw_visual.py plt.scatter()
plt.plot().
, rw.x_values rw.y_values linewidth. -
5000 50000.
15-4. : RandomWalk x_step y_step
.
[1, -1], [0, 1, 2, 3, 4]. -
, .
(, 0 8) 1
x y.
15-5. : fill_walk() .
get_step(), , -
. fill_walk()
get_step():
x_step = get_step()

y_step = get_step()
fill_walk(), .

Pygal
Pygal -
.
, ,
.
-, Pygal
; ,
.
.

1 6. ,
, . ,
, ,
.
, , .

. , -
, (, ..).
328 15

Pygal
Pygal pip. ( pip,
Python pip . 227.)
Linux OS X :
pip install --user pygal

Windows :
python -m pip install --user pygal

, pip3 pip.
, --user.

Pygal
, Pygal,
: http://www.pygal.org/,
Documentation, Chart types. -
, ,
.



:
die.py
from random import randint
class Die():
""", ."""

def __init__(self, num_sides=6):


""" ."""
self.num_sides = num_sides

def roll(self):
"""" 1 ."""
return randint(1, self.num_sides)

__init__() .
,
. ,
. (
: D6,
D8 ..)
Pygal 329

roll() randint()
1 . -
, (num_sides) .


, D6, -
, :
die_visual.py
from die import Die

# D6.
die = Die()

# .
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)

print(results)

Die .
100 , -
results. :
[4, 6, 5, 6, 1, 5, 6, 3, 5, 3, 5, 3, 2, 2, 1, 3, 1, 5, 3, 6, 3, 6, 5, 4,
1, 1, 4, 2, 3, 6, 4, 2, 6, 4, 1, 3, 2, 5, 6, 3, 6, 2, 1, 1, 3, 4, 1, 4,
3, 5, 1, 4, 5, 5, 2, 3, 3, 1, 2, 3, 5, 6, 2, 5, 6, 1, 3, 2, 1, 1, 1, 6,
5, 5, 2, 2, 6, 4, 1, 4, 5, 1, 1, 1, 4, 5, 3, 3, 1, 3, 5, 4, 5, 6, 5, 4,
1, 5, 1, 2]

, Die . -
1 6,
; 0 7 , ,
.
1 6, .


D6, ,
:
die_visual.py
...
# .
results = []
for roll_num in range(1000):
result = die.roll()
results.append(result)
330 15

# .
frequencies = []
for value in range(1, die.num_sides+1):
frequency = results.count(value)
frequencies.append(frequency)

print(frequencies)

Pygal , ,
1000 .
frequencies, .
( 1 6 ) ,
,
frequencies .
:
[155, 167, 168, 170, 159, 181]

: ,
D6,
. .


, . -
,
. :
die_visual.py
import pygal
...

# .
frequencies = []
for value in range(1, die.num_sides+1):
frequency = results.count(value)
frequencies.append(frequency)

# .
hist = pygal.Bar()

hist.title = "Results of rolling one D6 1000 times."


hist.x_labels = ['1', '2', '3', '4', '5', '6']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"

hist.add('D6', frequencies)
hist.render_to_file('die_visual.svg')

, pygal.Bar(), -
hist . title
Pygal 331

hist ( , ), -
D6 x ,
. add()
(
, ). ,
SVG, .svg.
.
, die_visual.svg ( ,
die_visual.py). ,
. 15.11. ( ; Pygal
, .)

. 15.11. , Pygal

,
Pygal: , ,
.
.



. D6,
. ( -
) results. die_visual.
py dice_visual.py :

dice_visual.py
import pygal
332 15

from die import Die

# D6.
die_1 = Die()
die_2 = Die()

# .
results = []
for roll_num in range(1000):
result = die_1.roll() + die_2.roll()
results.append(result)

# .
frequencies = []
max_result = die_1.num_sides + die_2.num_sides
for value in range(2, max_result+1):
frequency = results.count(value)
frequencies.append(frequency)

# .
hist = pygal.Bar()

hist.title = "Results of rolling two D6 dice 1000 times."


hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"

hist.add('D6 + D6', frequencies)


hist.render_to_file('dice_visual.svg')

Die,
. (12) -
; max_result .

.
2 max_result . (
range(2, 13), D6.
,
. ,
.)
, x .
( x_labels , -
.)
;
. 15.12.
,
D6. , 2 12,
7, : 1+6, 2+5,
3+4, 4+3, 5+2 6+1.
Pygal 333

. 15.12. 1000


6 10 , ,
50000 :
different_dice.py
from die import Die

import pygal

# D6 D10.
die_1 = Die()
die_2 = Die(10)

# .
results = []
for roll_num in range(50000):
result = die_1.roll() + die_2.roll()
results.append(result)

# Analyze the results.


...

# .
hist = pygal.Bar()

hist.title = "Results of rolling a D6 and a D10 50,000 times."


hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12',
'13', '14', '15', '16']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"
hist.add('D6 + D10', frequencies)
334 15

hist.render_to_file('dice_visual.svg')

D10, 10
Die1 50000
1000. , , 2, -
16; , x
.
. 15.13 . -
. , (1+1)
(6+10) -
, D6
: 7, 8, 9, 10 11 . ,
,
.

. 15.13. 50000 -

Pygal -
. -
.


15-6. : die.py dice_visual.py. ,
hist.x_labels, ,
. ,
for die_visual.py dice_visual.py .
335

15-7. D8s: , , 1000--


. ,
, .
15-8. : 3 D6 3,
18. , , -
D6.
15-9. :
. , ,
.
15-10. : matplotlib -
, Pygal .

-
.
matplotlib .
, Pygal
-
.
-
. -
,
.
, , ,
, , ?
16
matplotlib Pygal .
16

-
.
, -
.
, .
,
CSV JSON. Python csv
CSV ( )
. matplotlib
.
json
, JSON, Pygal
.

-
.
-
.

CSV

, ;
CSV ( Comma Separated Values, , ). -
, CSV :
2014-1-5,61,44,26,18,7,-1,56,30,9,30.34,30.27,30.15,,,,10,4,,0.00,0,,195

5 2014 . (). -
,
. CSV, -
,
.
CSV, -
;
CSV 337

https://www.nostarch.com/pythoncrashcourse/.
sitka_weather_07-2014.csv , .
(
.)

http://www.wunderground.com/history/.

CSV
Python csv CSV -
. ,
:
highs_lows.py
import csv

filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
print(header_row)

csv
filename. ,
f . csv.reader()
, .
reader.
csv next(),
.
next() , -
. header_row. ,
header_row , ,
:
['AKDT', 'Max TemperatureF', 'Mean TemperatureF', 'Min TemperatureF',
'Max Dew PointF', 'MeanDew PointF', 'Min DewpointF', 'Max Humidity',
' Mean Humidity', ' Min Humidity', ' Max Sea Level PressureIn',
' Mean Sea Level PressureIn', ' Min Sea Level PressureIn',
' Max VisibilityMiles', ' Mean VisibilityMiles', ' Min VisibilityMiles',
' Max Wind SpeedMPH', ' Mean Wind SpeedMPH', ' Max Gust SpeedMPH',
'PrecipitationIn', ' CloudCover', ' Events', ' WindDirDegrees']

reader , , -
. AKDT Alaska Daylight
Time (, ). ,
. Max
TemperatureF , -
.
, .
338 16

; ,
. -
, .


,
:
highs_lows.py
...
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)

for index, column_header in enumerate(header_row):


print(index, column_header)

enumerate()
. ( : print(header_row)
.)
:
0 AKDT
1 Max TemperatureF
2 Mean TemperatureF
3 Min TemperatureF
...
20 CloudCover
21 Events
22 WindDirDegrees

,
0 1. , -
sitka_weather_07-2014.csv
0 1.


, ; .
:
highs_lows.py
import csv

# .
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
CSV 339

highs = []
for row in reader:
highs.append(row[1])

print(highs)

highs -
. reader ,
CSV,
. ,
, .
1 ( ) highs .
highs :
['64', '71', '64', '59', '69', '62', '61', '55', '57', '61', '57', '59', '57',
'61', '64', '61', '59', '63', '60', '57', '69', '63', '62', '59', '57', '57',
'61', '59', '61', '61', '66']


.
int() ,
matplotlib:
highs_lows.py
...
highs = []
for row in reader:
high = int(row[1])
highs.append(high)

print(highs)


. -
:
[64, 71, 64, 59, 69, 62, 61, 55, 57, 61, 57, 59, 57, 61, 64, 61, 59, 63, 60, 57,
69, 63, 62, 59, 57, 57, 61, 59, 61, 61, 66]


-
matplotlib:
highs_lows.py
import csv

from matplotlib import pyplot as plt


340 16

# .
...

# .
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(highs, c='red')

# .
plt.title("Daily high temperatures, July 2014", fontsize=24)
plt.xlabel('', fontsize=16)
plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=16)

plt.show()

plot() highs c='red' -


. ( ,
.) (-
, ) , 15.
, x , plt.xlabel() -
, . . 16.1
:
2014 . ( ).

. 16.1.
2014 . ( )

datetime
, .
:
2014-7-1,64,56,50,53,51,48,96,83,58,30,19,...
CSV 341

, -
'2014-7-1' , .
, 1 2014 , strptime()
datetime. , strptime() :
>>> from datetime import datetime
>>> first_date = datetime.strptime('2014-7-1', '%Y-%m-%d')
>>> print(first_date)
2014-07-01 00:00:00

datetime datetime.
strptime(), .
Python, .
'%Y-' Python, ,
, ; '%m-'
Python , -
; , '%d' Python
1 31.
strptime() , ,
. .16.1
.

16.1. datetime


%A , Monday
%B , January
%m ( 01 12)
%d ( 01 31)
%Y (, 2015)
%y (, 15)
%H 24- ( 00 23)
%I 12- ( 01 12)
%p AM PM
%M ( 00 59)
%S ( 00 59)


CSV,
. -
plot():
highs_lows.py
import csv
342 16

from datetime import datetime

from matplotlib import pyplot as plt

# .
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)

dates, highs = [], []


for row in reader:
current_date = datetime.strptime(row[0], "%Y-%m-%d")
dates.append(current_date)

high = int(row[1])
highs.append(high)

# .
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')

# .
plt.title("Daily high temperatures, July 2014", fontsize=24)
plt.xlabel('', fontsize=16)

fig.autofmt_xdate()
plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=16)

plt.show()

. 16.2. x
CSV 343


. ,
(row[0]), datetime , dates.
plot() . fig.autofmt_
xdate() , .
. 16.2 .


, .
. sitka_weather_2014.csv, -
, .
:
highs_lows.py
...
# .
filename = 'sitka_weather_2014.csv'
with open(filename) as f:
...
# .
plt.title("Daily high temperatures - 2014", fontsize=24)
plt.xlabel('', fontsize=16)
...

filename ,
sitka_weather_2014.csv ,
.
. 16.3 .

. 16.3.
344 16


. 16.3
, , -
.
:
highs_lows.py
...
# , .
filename = 'sitka_weather_2014.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)

dates, highs, lows = [], [], []


for row in reader:
current_date = datetime.strptime(row[0], "%Y-%m-%d")
dates.append(current_date)

high = int(row[1])
highs.append(high)

low = int(row[3])
lows.append(low)

# .
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')
plt.plot(dates, lows, c='blue')

# .
x plt.title("Daily high and low temperatures - 2014", fontsize=24)
...

. 16.4.
CSV 345

lows ,

(row[3]) . -
plot() ,
. .
. 16.4 .



. :
-
. fill_between(),
x y
y:
highs_lows.py
...
# .
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red', alpha=0.5)
plt.plot(dates, lows, c='blue', alpha=0.5)
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
...

alpha . 0
, 1 ( ) .
alpha=0.5 .

. 16.5.
346 16

fill_between() dates x
y highs lows. facecolor -
; alpha=0.1,
, .
. 16.5 highs lows.

.


highs_lows.py
. , -
( ).
; , -
.
(
). death_valley_2014.csv
, highs_lows.py
:
highs_lows.py
...
# , .
filename = 'death_valley_2014.csv'
with open(filename) as f:
...

, -
:
Traceback (most recent call last):
File "highs_lows.py", line 17, in <module>
high = int(row[1])
ValueError: invalid literal for int() with base 10: ''

, Python -
, ('')
. , death_valley_2014.csv:
2014-2-16,,,,,,,,,,,,,,,,,,,0.00,,,-1

, 16 2014 ; -
. ,
,
. :
highs_lows.py
...
# , .
filename = 'death_valley_2014.csv'
CSV 347

with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)

dates, highs, lows = [], [], []


for row in reader:
try:
current_date = datetime.strptime(row[0], "%Y-%m-%d")
high = int(row[1])
low = int(row[3])
except ValueError:
print(current_date, 'missing data')
else:
dates.append(current_date)
highs.append(high)
lows.append(low)

# Plot data.
...

#
title = "Daily high and low temperatures - 2014\nDeath Valley, CA"
plt.title(title, fontsize=20)
...

,
. - , Python -
ValueError, ,
.
. , , -
, else, -
.
, , .

. 16.6.
348 16

highs_lows.py ,
:
2014-02-16 missing data
.16.6.
, , -
, - ( ),
.
.
, , -
, .
,
. -
try-except-else. continue
, remove()
del. -
, .


16-1. -: -:
? - .
( http://www.
wunderground.com/history/. ,
Comma-Delimited File. -
CSV.)
16-2. :
.
, y. -
y . 16.5 16.6 -
( ,
). .
16-3. : .
, ,
.
16-4. : ,
.

JSON
JSON
json. Pygal
, , -
.


population_data.json,
1960 2010 , .
JSON 349

,
Open Knowledge Foundation (http://data.okfn.org/).


population_data.json ,
:
population_data.json
[
{
"Country Name": "Arab World",
"Country Code": "ARB",
"Year": "1960",
"Value": "96388069"
},
{
"Country Name": "Arab World",
"Country Code": "ARB",
"Year": "1961",
"Value": "98882541.4"
},
...
]

Python.
: (Country Name),
(Country Code), (Year) (Value), -
. -
2010 , ,
:
world_population.py
import json

# .
filename = 'population_data.json'
with open(filename) as f:
pop_data = json.load(f)

# 2010 .
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = pop_dict['Value']
print(country_name + ": " + population)

json,
. pop_data . -
json.load() , Python:
. ,
350 16

pop_data.
, pop_dict.
'Year' 2010. (
population_data.json , .)
2010 , , 'Country
Name', country_name, ,
'Value', population . -
.
-
:
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Zimbabwe: 12571000

, -
. ,
Pygal.


population_data.json .
,
. int():
world_population.py
...
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = int(pop_dict['Value'])
print(country_name + ": " + str(population))

-
.
. , :
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Traceback (most recent call last):
File "print_populations.py", line 12, in <module>
population = int(pop_dict['Value'])
ValueError: invalid literal for int() with base 10:
'1127437398.85751'

,
. -
JSON 351

- , Python
'1127437398.85751' . (,
, -
.) ,
, :
world_population.py
...
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
print(country + ": " + str(population))

float() , int()
.
2010 :
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Zimbabwe: 12571000

,
. : ,
.


,
. Pygal
: -
, .
, -
; , population_data.json, ,
Pygal . -
.
Pygal i18n ( internationalization).
COUNTRIES ,
. ,
i18n :

countries.py
from pygal.i18n import COUNTRIES
for country_code in sorted(COUNTRIES.keys()):
print(country_code, COUNTRIES[country_code])

for . -
, :
352 16

ad Andorra
ae United Arab Emirates
af Afghanistan
...
zw Zimbabwe

, COUNTRIES .
country_codes,
:
country_codes.py
from pygal.i18n import COUNTRIES
def get_country_code(country_name):
""" Pygal, 2 ."""
for code, name in COUNTRIES.items():
if name == country_name:
return code
# , None.
return None

print(get_country_code('Andorra'))
print(get_country_code('United Arab Emirates'))
print(get_country_code('Afghanistan'))

get_country_code() -
country_name .
COUNTRIES. ,
, , None .
, .
, :
ad
ae
af

, print
country_codes.py.
get_country_code() world_population.py:
world_population.py
import json

from country_codes import get_country_code


...

# 2010 .
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country_name)
if code:
print(code + ": "+ str(population))
JSON 353

else:
print('ERROR - ' + country_name)

code None,
. , -
print . ,
, . ,
:
ERROR - Arab World
ERROR - Caribbean small states
ERROR - East Asia & Pacific (all income levels)
...
af: 34385000
al: 3205000
dz: 35468000
...
ERROR - Yemen, Rep.
zm: 12927000
zw: 12571000

. -, -
;
. -,
(Yemen, Rep. Yemen).
, , ,
.


. Pygal -
Worldmap,
. Worldmap -
, :
americas.py
import pygal

wm = pygal.Worldmap()
wm.title = 'North, Central, and South America'

wm.add('North America', ['ca', 'mx', 'us'])


wm.add('Central America', ['bz', 'cr', 'gt', 'hn', 'ni', 'pa', 'sv'])
wm.add('South America', ['ar', 'bo', 'br', 'cl', 'co', 'ec', 'gf',
'gy', 'pe', 'py', 'sr', 'uy', 've'])

wm.render_to_file('americas.svg')

Worldmap title
. add(),
, . add()

354 16

.
, 'ca', 'mx' 'us' ,
add(), ,
. -
.
render_to_file() .svg ; -
. ,
(. 16.7).

. 16.7. Worldmap

, , -
.
.


,
:
na_populations.py
import pygal
wm = pygal.Worldmap()
wm.title = 'Populations of Countries in North America'
wm.add('North America', {'ca': 34126000, 'us': 309349000, 'mx':
113423000})

wm.render_to_file('na_populations.svg')
JSON 355

. 16.8.

Worldmap . -
add(), -
. Pygal ()
(). Pygal
( ) ( ). .16.8
.
: ,
. .


, -
Pygal:
,
. world_population.py:
world_population.py
import json

import pygal

from country_codes import get_country_code

# .
...

# .
356 16

cc_populations = {}
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country)
if code:
cc_populations[code] = population

wm = pygal.Worldmap()
wm.title = 'World Population in 2010, by Country'
wm.add('2010', cc_populations)

wm.render_to_file('world_population.svg')

pygal.
, Pygal. -
cc_populations;
, .
print.
Worldmap title . add()
.
. 16.9 .
, , ,
.
,
.

. 16.9. 2010
JSON 357

, . -
,
, . -
,
.


, -
. ,
,
300 .
,
: 10 , 10 1
1 :
world_population.py
...
# .
cc_populations = {}
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
--snip--
if code:
cc_populations[code] = population

# 3 .
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():
if pop < 10000000:
cc_pops_1[cc] = pop
elif pop < 1000000000:
cc_pops_2[cc] = pop
else:
cc_pops_3[cc] = pop

# .
print(len(cc_pops_1), len(cc_pops_2), len(cc_pops_3))

wm = pygal.Worldmap()
wm.title = 'World Population in 2010, by Country'
x wm.add('0-10m', cc_pops_1)
wm.add('10m-1bn', cc_pops_2)
wm.add('>1bn', cc_pops_3)

wm.render_to_file('world_population.svg')

, .
cc_populations -
. if-elif-else (cc_pops_1,
cc_pops_2 cc_pops_3) .
358 16

. 16.10. 2010

.

Worldmap. :
85 69 2

, 85 10 ,
69 10 1
1 .
. .16.10.
.

.

Pygal
, -
: , Pygal
- . Pygal
.
Pygal ,

:
world_population.py
import json
JSON 359

import pygal
from pygal.style import RotateStyle
...
# 3 .
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():
if pop < 10000000:
...
wm_style = RotateStyle('#336699')
wm = pygal.Worldmap(style=wm_style)
wm.title = 'World Population in 2010, by Country'
...

Pygal style,
RotateStyle . RGB -
. Pygal -
.
(#), : -
,
. 00 ( -
) FF ( ).

RGB. , (#336699),
(33), (66) (99). RotateStyle
- .
RotateStyle , wm_style.
, -
Worldmap . . 16.11 .

. 16.11.
360 16

-
.


Pygal .
LightColorizedStyle. -
, , -
. , :
from pygal.style import LightColorizedStyle

LightColorizedStyle :
wm_style = LightColorizedStyle

, -
Pygal . ,
LightColorizedStyle RotateStyle.
LightColorizedStyle RotateStyle:
from pygal.style import LightColorizedStyle, RotateStyle

RotateStyle,
base_style:
wm_style = RotateStyle('#336699', base_style=LightColorizedStyle)

, -
, .
.
,
,
import:
from pygal.style import LightColorizedStyle as LCS, RotateStyle as RS

:
wm_style = RS('#336699', base_style=LCS)

, -
Pygal.


16-5. : , ,
12 . ,
, COUNTRIES. if-elif get_country_code(),
:
if country_name == 'Yemen, Rep.'
return 'ye'
elif ...
361

COUNTRIES, return None.


, .
16-6. : Open Knowledge Foundation -
() ;
http://data.okfn.org/data/core/gdp/.
JSON -
.
16-7. :
, . http://data.worldbank.org/indicator/ -
, . ,
Download Data CSV. CSV,
Metadata; CSV. -
;
Pygal, .
Worldmap .
16-8. country_codes: country_codes
print get_country_code().
, 11.

. ,
CSV JSON , -
. , -
matplotlib, datetime
.
, Pygal
Pygal.
CSV JSON
, .
. -

.

, .
, ,
,
.
17 API


. -
(API) -
( ).
. -
, ,
,
.

API -
API - -,
,
URL- .
API. (, JSON
CSV). , (
, ),
API.

Git GitHub
GitHub , -
. API
GitHub Python
Pygal.
GitHub (https://github.com/) Git
,
. Git ,
, , ,
. ,
Git , .
, , Git
. ,
Git .
API - 363

( Git
.) GitHub , -
, : , ,
..
GitHub,
, ,
. -
Python
GitHub, .

API
GitHub API ( )
API. , API,
Enter:
https://api.github.com/search/repositories?q=language:python&sort=stars
Python, GitHub -
, Python.
: https://api.github.com/ -
GitHub, API. , search/
repositories, API GitHub.
repositories ,
. q (Query), -
(q=). language:python ,
,
Python. , &sort=stars, -
.
. ,
, URL-
.
{
"total_count": 713062,
"incomplete_results": false,
"items": [
{
"id": 3544424,
"name": "httpie",
"full_name": "jkbrzt/httpie",
...

, GitHub
713062 Python. "incomplete_results" false,
, ( ).
GitHub API,
true.
"items" Python GitHub.
364 17 API

requests
requests
Python . requests,
:
$ pip install --user requests

pip, Python
pip . 227. (,
.)

API
, API Github
Python :
python_repos.py
import requests

# API .
url = 'https://api.github.com/search/repositories?q=language:python
&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

# API .
response_dict = r.json()

# .
print(response_dict.keys())

requests. URL- API -


, requests .
get() URL,
r. status_code,
. ( 200 .)
status_code,
, .
API JSON,
json() Python.
response_dict.
, response_dict,
:
Status code: 200
dict_keys(['items', 'total_count', 'incomplete_results'])

200 , . -
: items, 'total_count' 'incomplete_results'.
API - 365


, -
, 'incomplete_results, . ,
API, .


, API ,
. -
, ,
.
python_repos.py
import requests

# API .
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

# API .
response_dict = r.json()
print("Total repositories:", response_dict['total_count'])

# .
repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))

# .
repo_dict = repo_dicts[0]
print("\nKeys:", len(repo_dict))
for key in sorted(repo_dict.keys()):
print(key)

, 'total_count',
Python GitHub.
, 'items', ,
Python.
repo_dicts. repo_dicts,
, -
.
,
, repo_dicts
repo_dict . -
.
; , .
:
Status code: 200
Total repositories: 713062
366 17 API

Repositories returned: 30

Keys: 68
archive_url
assignees_url
blobs_url
...
url
watchers
watchers_count

API GitHub : repo_


dict 68 . ,
. ( ,
API, , -
, .)
repo_dict:
python_repos.py
...
# .
repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))

# .
repo_dict = repo_dicts[0]

print("\nSelected information about first repository:")


print('Name:', repo_dict['name'])
print('Owner:', repo_dict['owner']['login'])
print('Stars:', repo_dict['stargazers_count'])
print('Repository:', repo_dict['html_url'])
print('Created:', repo_dict['created_at'])
print('Updated:', repo_dict['updated_at'])
print('Description:', repo_dict['description'])

, -
. . -
, owner
, , login
.
, , URL GitHub . -
.
; :
Status code: 200
Total repositories: 713065
Repositories returned: 30

Selected information about first repository:


Name: httpie
Owner: jkbrzt
Stars: 16101
API - 367

Repository: https://github.com/jkbrzt/httpie
Created: 2012-02-25T12:39:13Z
Updated: 2015-07-13T14:56:41Z
Description: CLI HTTP client; user-friendly cURL replacement featuring
intuitive UI, JSON support, syntax highlighting, wget-like downloads,
extensions, etc.

,
Python GitHub HTTPie,
jkbrzt, 16000 GitHub.
URL , ( 2012 .) ,
. , , HTTPie
HTTP (CLI Command Line Interface,
).



. -
, API,
:
python_repos.py
...
# .
repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))
print("\nSelected information about each repository:")
for repo_dict in repo_dicts:
print('\nName:', repo_dict['name'])
print('Owner:', repo_dict['owner']['login'])
print('Stars:', repo_dict['stargazers_count'])
print('Repository:', repo_dict['html_url'])
print('Description:', repo_dict['description'])

.
repo_dicts. , ,
, URL GitHub :
Status code: 200
Total repositories: 713067
Repositories returned: 30

Selected information about each repository:

Name: httpie
Owner: jkbrzt
Stars: 16101
Repository: https://github.com/jkbrzt/httpie
Description: CLI HTTP client; user-friendly cURL replacement featuring
intuitive UI, JSON support, syntax highlighting, wget-like downloads,
extensions, etc.
368 17 API

Name: django
Owner: django
Stars: 15028
Repository: https://github.com/django/django
Description: The Web framework for perfectionists with deadlines.
...

Name: powerline
Owner: powerline
Stars: 4315
Repository: https://github.com/powerline/powerline
Description: Powerline is a statusline plugin for vim, and provides
statuslines and prompts for several other applications, including zsh, bash,
tmux, IPython, Awesome and Qtile.

; , -
,
, .

API
API ; ,
. ,
GitHub,
https://api.github.com/rate_limit. , :
{
"resources": {
"core": {
"limit": 60,
"remaining": 58,
"reset": 1426082320
},
"search": {
"limit": 10,
"remaining": 8,
"reset": 1426078803
}
},
"rate": {
"limit": 60,
"remaining": 58,
"reset": 1426082320
}
}

API .
, 10
8 . reset Unix-,
( , 1 1970 ) -
, .
,
API. , , .
API - 369

API API .
GitHub , , API,
.

Pygal
, , , -
Python GitHub.
: -
.
GitHub. :
python_repos.py
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

# API .
URL = 'https://api.github.com/search/repositories?q=language:python&sort=star'
r = requests.get(URL)
print("Status code:", r.status_code)

# API .
response_dict = r.json()
print("Total repositories:", response_dict['total_count'])

# .
repo_dicts = response_dict['items']

names, stars = [], []


for repo_dict in repo_dicts:
names.append(repo_dict['name'])
stars.append(repo_dict['stargazers_count'])

# .
my_style = LS('#333366', base_style=LCS)
chart = pygal.Bar(style=my_style, x_label_rotation=45, show_
legend=False)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names

chart.add('', stars)
chart.render_to_file('python_repos.svg')

pygal Pygal,
. API -
,
API. ,
.
, -
. ( ) -
370 17 API

, . -
.
LightenStyle (-
LS ) . -
base_style LightColorizedStyle (
LCS). Bar() ,
my_style. :
45 x (x_label_rotation=45 ), -
,
(show_legend=False). ,
x_labels names.
,
. . 17.1.
, ,
Python.

. 17.1. Python GitHub

Pygal
.
, :
, , -
Bar():
python_repos.py
...

# .
my_style = LS('#333366', base_style=LCS)
my_config = pygal.Config()
API - 371

my_config.x_label_rotation = 45
my_config.show_legend = False
my_config.title_font_size = 24
my_config.label_font_size = 14
my_config.major_label_font_size = 18
my_config.truncate_label = 15
my_config.show_y_guides = False
my_config.width = 1000
chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names

chart.add('', stars)
chart.render_to_file('python_repos.svg')

Pygal Config my_config; -


my_config .
x_label_rotation show_legend , -
Bar.
, -
.
x y.
y , 5000 .
, .
truncate_label
15 . ( ,
.) -
, show_y_guides False.
,
.
Bar my_config -
; , .

. 17.2.
372 17 API

my_config -
; . . 17.2 -
.


Pygal -
, .
(tooltip) .
, .
, -
, .
add() :
bar_descriptions.py
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

my_style = LS('#333366', base_style=LCS)


chart = pygal.Bar(style=my_style, x_label_rotation=45, show_legend=False)
chart.title = 'Python Projects'
chart.x_labels = ['httpie', 'django', 'flask']

plot_dicts = [
{'value': 16101, 'label': 'Description of httpie.'},
{'value': 15028, 'label': 'Description of django.'},
{'value': 14798, 'label': 'Description of flask.'},
]

chart.add('', plot_dicts)
chart.render_to_file('bar_descriptions.svg')

. 17.3.
API - 373

plot_dicts ,
: HTTPie, Django Flask.
: 'value' 'label'. Pygal ,
'value', , , 'label',
. , -
, 16101 ,
Description of httpie.
add() . add()
, (plot_dicts ) . -
. 17.3. Pygal
,
.


, plot_dicts
30 , API.
python_repos.py
...
# .
repo_dicts = response_dict['items']
print("Number of items:", len(repo_dicts))

names, plot_dicts = [], []


for repo_dict in repo_dicts:
names.append(repo_dict['name'])

plot_dict = {
'value': repo_dict['stargazers_count'],
'label': repo_dict['description'],
}
plot_dicts.append(plot_dict)

# .
my_style = LS('#333366', base_style=LCS)
...

chart.add('', plot_dicts)
chart.render_to_file('python_repos.svg')

, names plot_dicts. names


x.
plot_dict . -
'value', 'label'.
plot_dict plot_dicts . -
plot_dicts add().
.17.4.
374 17 API

. 17.4.


Pygal
. ,
, , .
plot_dict
'xlink':
python_repos.py
...
names, plot_dicts = [], []
for repo_dict in repo_dicts:
names.append(repo_dict['name'])

plot_dict = {
'value': repo_dict['stargazers_count'],
'label': repo_dict['description'],
'xlink': repo_dict['html_url'],
}
plot_dicts.append(plot_dict)
...

Pygal URL-, 'xlink',


. , -
GitHub -
. , ,
, API!
API - 375

API Hacker News


API , -
Hacker News (http://news.ycombinator.com/). -
,
, . API Hacker News
, -
.

( ):
https://hacker-news.firebaseio.com/v0/item/9884165.json


9884165:
{
'url': 'http://www.bbc.co.uk/news/science-environment-33524589',
'type': 'story',
'title': 'New Horizons: Nasa spacecraft speeds past Pluto',
'descendants': 141,
'score': 230,
'time': 1436875181,
'text': '',
'by': 'nns',
'id': 9884165,
'kids': [9884723, 9885099, 9884789, 9885604, 9885844]
}

, , ,
'url' 'title' . 'descendants' ,
. 'kids'
, .
,
.
API , -
Hacker News, :
hn_submissions.py
import requests

from operator import itemgetter

# API .
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url)
print("Status code:", r.status_code)

# .
submission_ids = r.json()
submission_dicts = []
for submission_id in submission_ids[:30]:
376 17 API

# API .
url = ('https://hacker-news.firebaseio.com/v0/item/' +
str(submission_id) + '.json')
submission_r = requests.get(url)
print(submission_r.status_code)
response_dict = submission_r.json()

submission_dict = {
'title': response_dict['title'],
'link': 'http://news.ycombinator.com/item?id=' + str(submission_id),
'comments': response_dict.get('descendants', 0)
}
submission_dicts.append(submission_dict)

submission_dicts = sorted(submission_dicts,
key=itemgetter('comments'),
reverse=True)
for submission_dict in submission_dicts:
print("\nTitle:", submission_dict['title'])
print("Discussion link:", submission_dict['link'])
print("Comments:", submission_dict['comments'])

API . API
500 Hacker News
. Python ,
submission_ids. -
,
.
submission_dicts -
. 30
API , URL
submission_id . , -
, .
, -
.
. -
, 'descendants' . ,
, dict.get(), ,
( ), , ( -
), 0 . , submission_dict
submission_dicts.
Hacker News ,
: ,
. -
. itemgetter()
operator. 'comments', ,
, . sorted()
.
,
.
API - 377

,
: , -
:
Status code: 200
200
200
200
..

Title: Firefox deactivates Flash by default


Discussion link: http://news.ycombinator.com/item?id=9883246
Comments: 231

Title: New Horizons: Nasa spacecraft speeds past Pluto


Discussion link: http://news.ycombinator.com/item?id=9884165
Comments: 142

Title: Iran Nuclear Deal Is Reached With World Powers


Discussion link: http://news.ycombinator.com/item?id=9884005
Comments: 141

Title: Match Group Buys PlentyOfFish for $575M


Discussion link: http://news.ycombinator.com/item?id=9884417
Comments: 75

Title: Our Nexus 4 devices are about to explode


Discussion link: http://news.ycombinator.com/item?id=9885625
Comments: 14
...

-
API. ,
,
.


17-1. : API python_repos.py , -
. -
, JavaScript, Ruby, C, Java, Perl, Haskell Go.
17-2. : hn_submissions.py -
, Hacker News.
.
,
.
17-3. python_repos.py: python_repos.py
API status_code. test_python_repos.py,
unittest , status_code 200. -
, , ,
, -
.
378 17 API

, API , -

. GitHub API
Python GitHub,
API Hacker News. ,
requests API GitHub
. Pygal, -

.
Django -.
3.
-
18 Django

-
,
. Python -
-. Django (http://
djangoproject.com/) Learning Log
, .
,
, . -
Django ,
, Django
.
Django - -
-. Django ,
,
. 19 20 Learning Log,
, ( ) .


.
.


, ,
.
-, -
.
, ,
. :
- Learning Log,

. Learning Log -
.
381

, ,
.

,
, -
. .


Django .
,
Python.

Learning Log 20.
learning_log ,
.
Python3, :
learning_log$ python -m venv ll_env
learning_log$

venv
ll_env. ,
. 382. - ,
virtualenv.

virtualenv
Python
venv, virtualenv. -
virtualenv :
$ pip install --user virtualenv

, .
( pip, Python
pip . 227.)

Linux, , virtualenv -
. , Ubuntu virtualenv
sudo apt-get install python-virtualenv.
learning_log
:
learning_log$ virtualenv ll_env
New python executable in ll_env/bin/python
Installing setuptools, pip...done.
learning_log$
382 18 Django

Python, , -
virtualenv. , virtualenv ll_env --python=python3
, Python 3.


,
:
learning_log$ source ll_env/bin/activate
(ll_env)learning_log$

activate ll_env/bin. -
, ;
, . , -
ll_env, , .

Windows, ll_env\Scripts\activate (
source) .
, deactivate:
(ll_env)learning_log$ deactivate
learning_log$

,
.

Django
, -
Django:
(ll_env)learning_log$ pip install Django
Installing collected packages: Django
Successfully installed Django
Cleaning up...
(ll_env)learning_log$

,
. --user ,
python -m pip install _.
, Django ,
.

Django
( ll_env
), :
383

(ll_env)learning_log$ django-admin.py startproject learning_log .


(ll_env)learning_log$ ls
learning_log ll_env manage.py
(ll_env)learning_log$ ls learning_log
__init__.py settings.py urls.py wsgi.py

Django learning_log.
,
.

, -
. , ( ll_env)
.
ls (dir Windows) , Django -
learning_log. manage.py ,
Django .
,
.
learning_log , -
settings.py, urls.py wsgi.py. settings.py , Django
.

. urls.py Django,
. wsgi.py Django -
( Web Server Gateway Interface).


Django , ,
, , Django .
Learning Log, (
):
(ll_env)learning_log$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: contenttypes, sessions, auth, admin
...
Applying sessions.0001_initial... OK
(ll_env)learning_log$ ls
db.sqlite3 learning_log ll_env manage.py

. -
migrate Django , -
.
SQLite ( SQLite ), Django
. Django
, ,
384 18 Django

(Synchronize unmigrated apps), , -


(Apply all migrations).
ls , Django
db.sqlite3 . SQLite , ;
,
.


, . runserver:
(ll_env)learning_log$ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
July 15, 2015 - 06:23:51
Django version 1.8.4, using settings 'learning_log.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Django ,
, . , URL -
, Django ;
.
Django ; -
Django ;
URL-, . URL http://127.0.0.1:8000/ ,
8000 (localhost),
. ,
;
.
URL http://localhost:8000/
http://127.0.0.1:8000/, .
. 18.1 , Django, ,
. (,
, Ctrl+C).

, Django -
; python manage.py runserver 8001
, .


18-1. : , Django,
, .
InstaBook FaceGram ( learning_log), -
. Django -
django-admin.py startproject instabook. (
).
385

, , -
Learning Log. , ,
Django , -
.

. 18.1.


Django ,
.
, .
-
19.
runserver
, . ( )
, manage.py.
startapp:
learning_log$ source ll_env/bin/activate
(ll_env)learning_log$ python manage.py startapp learning_logs
(ll_env)learning_log$ ls
db.sqlite3 learning_log learning_logs ll_env manage.py
(ll_env)learning_log$ ls learning_logs/
admin.py __init__.py migrations models.py tests.py views.py

startapp _ Django ,
. ,
learning_logs . ,
, Django .
models.py, admin.py views.py.
models.py , -
. admin.py views.py
.
386 18 Django


, .
. , , -
, .
, ,
.
models.py :
models.py
from django.db import models

# .

models ,
. Django, , -
.
; , , -
. ,
:
from django.db import models

class Topic(models.Model):
""", """
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
""" ."""
return self.text

Topic, Model ,
Django .
Topic : text date_added.
text CharField , ,
. CharField -
: , , ..
CharField Django, -
.
max_length, 200 ;
.
date_added DateTimeField
. auto_add_now=True Django
,
.

, , Django
Model Field Reference https://docs.djangoproject.com/en/1.8/ref/models/fields/. ,
387

, ,
.
Django, -
. Django __str__()
. __str__(),
, text .

Python 2.7, __str__() __unicode__().


.


, Django
. settings.py ( learning_log/learning_log)
, Django,
:
settings.py
...
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
...

, Django, -
. ; INSTALLED_
APPS, :
...
INSTALLED_APPS = (
...
'django.contrib.staticfiles',

#
'learning_logs',
)
...

,
, . ,
learning_logs.
Django -
, Topic.
:
388 18 Django

(ll_env)learning_log$ python manage.py makemigrations learning_logs


Migrations for 'learning_logs':
0001_initial.py:
- Create model Topic
(ll_env)learning_log$

makemigrations Django ,
, . ,
Django 0001_initial.py.
Topic.
:
(ll_env)learning_log$ python manage.py migrate
...
Running migrations:
Rendering model states... DONE
Applying learning_logs.0001_initial... OK

,
migrate. ;
Django , learning_logs -
.
, , Learning
Log, : models.py ,
makemigrations learning_logs Django -
(migrate).

Django
Django , ,
. ,
.
Topic.


Django ,
; . -
, .
-
. -
, , -
.
- ,
. -
,
, .
Django, -
:
389

(ll_env)learning_log$ python manage.py createsuperuser


Username (leave blank to use 'ehmatthes'): ll_admin
Email address:
Password:
Password (again):
Superuser created successfully.
(ll_env)learning_log$

createsuperuser Django -
, . ll_admin,
.
.
.

. ,
Django ; -
, . , Django
. ,
. ,
, .
.


Django (, User Group) -
, , ,
.
learning_logs Django admin.py
models.py:
admin.py
from django.contrib import admin

# .

Topic ,
:
from django.contrib import admin

from learning_logs.models import Topic


admin.site.register(Topic)

Topic , admin.site.
register() ,
.
-
. http://localhost:8000/admin/,
, -
. 18.2. -
390 18 Django

, .
,
Topic.

. 18.2. Topic

-, ,
Django . ,
python manage.py runserver.


Topic ,
. Topics, Topics; -
,
. Add;
. Chess Save. -
Topics,
.
, .
Add Rock Climbing. Save -
Topics, , Chess Rock
Climbing.

Entry
, ,
, -
. .
--,
.
391

Entry :
models.py
from django.db import models

class Topic(models.Model):
...

class Entry(models.Model):
""", """
topic = models.ForeignKey(Topic)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)

class Meta:
verbose_name_plural = 'entries'

def __str__(self):
""" ."""
return self.text[:50] + "..."

Entry Model,
Topic . , topic, ForeignKey .
(foreign key) ; -
. -
. ,
. ,
Django , .
, .
text, TextField .
,
. date_added -
.
Meta Entry. Meta -
;
, Django -
Entries . (
Django Entrys.) , __str__()
Django, -
. ,
Django 50 . -
.

Entry
,
. : models.py,
python manage.py makemigrations _, python
manage.py migrate.
392 18 Django

:
(ll_env)learning_log$ python manage.py makemigrations learning_logs
Migrations for 'learning_logs':
0002_entry.py:
- Create model Entry
(ll_env)learning_log$ python manage.py migrate
Operations to perform:
...
Applying learning_logs.0002_entry... OK

0002_entry.py,
Django, , -
Entry . migrate Django ,
.

Entry
Entry . admin.py :
admin.py
from django.contrib import admin

from learning_logs.models import Topic, Entry

admin.site.register(Topic)
admin.site.register(Entry)

http://localhost/admin/, Entries -
learning_logs. Add Entries Entries -
Add.
, , .
Chess . Save
. -
text[:50]
;
, .
Chess Rock Climbing,
Learning Log.

Django
-
. , (shell)
Django, .
:
(ll_env)learning_log$ python manage.py shell
>>> from learning_logs.models import Topic
>>> Topic.objects.all()
[<Topic: Chess>, <Topic: Rock Climbing>]
393

python manage.py shell ( )


Python, -
. Topic
learning_logs.models . Topic.objects.all()
Topic;
(queryset).
, -
. , , ,
:
>>> topics = Topic.objects.all()
>>> for topic in topics:
... print(topic.id, topic)
...
1 Chess
2 Rock Climbing

topics, id
topic . , Chess
1, Rock Climbing 2.
, -
. text date_added
Chess:
>>> t = Topic.objects.get(id=1)
>>> t.text
'Chess'
>>> t.date_added
datetime.datetime(2015, 5, 28, 4, 39, 11, 989446, tzinfo=<UTC>)

, .
topic Entry. ForeighKey,
. Django
, :
>>> t.entry_set.all()
[<Entry: The opening is the first part of the game, roughly...>, <Entry: In
the opening phase of the game, it's important t...>]

,
, ,
set . , Pizza Topping,
Topping Pizza .
my_pizza, Topping
my_pizza.topping_set.all().
-
, . ,
, .
, , ,
394 18 Django

, .
, ,
, , -.
,
, Django
.

,
. , trl+D; Windows
Ctrl+Z, Enter.


18-2. : __str__() Entry
Entry, Django -
. __str__() if,
, 50 .
, 50 , ,
.
18-3. Django API: -
. https://docs.
djangoproject.com/en/1.8/topics/db/queries/. , ,
, ,
.
18-4. : pizzeria, pizzas.
Pizza name, (-
, ). Topping pizza name.
pizza Pizza, name
, .
. -
. .

: Learning Log
- Django : -
URL, .
(patterns) URL. URL URL-
Django, -
URL- ,
.
URL-
, .
, ,
. , ,
Learning Log. URL-
, -
.
395

, Learning Log , -
, . ,
, ; ,
, , .
.

URL
, URL-
, , URL-
. URL : ,
. URL- http://localhost:8000/
, Django ; ,
. ,
URL- Learning Log.
learning_log urls.py. -
:
urls.py
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
]

, URL-
.
urlpatterns . urls.py, ,
urlpatterns URL- .
admin.site.urls, URL-,
.
URL- learning_logs:
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'', include('learning_logs.urls', namespace='learning_
logs')),
]

learning_logs.urls.
namespace, URL- learning_logs -
URL-, . -
.
urls.py learning_log;
urls.py learning_logs:
396 18 Django

urls.py
""" URL learning_logs."""

from django.conf.urls import url

from . import views

urlpatterns = [
#
url(r'^$', views.index, name='index'),
]

, urls.py , -
. url,
URL . views;
Python ,
urls.py. urlpatterns -
,
learning_logs .
URL url() .
. Django urlpatterns
, URL.
, ,
Django.
r'^$' . r Python, -
,
, .
^ , $ .
Python URL-,
URL. Python URL-
(http://localhost:8000/),
URL-. URL- -
, Django , URL -
URL.
url() . -
URL- , Django
views.index (
). index URL,
. ,
,
URL.

.
, , , . - , -
; .
397


, ,
,
, .
views.py learning_logs -
python manage.py startapp. :
views.py
from django.shortcuts import render

# .

render(),
, .
:
from django.shortcuts import render

def index(request):
""" Learning Log"""
return render(request, 'learning_logs/index.html')

URL , Django
views.py index(),
.
, render().
render() , -
. .


-. ,
Django .
, .
,
.
learning_logs templates.
templates learning_logs.
( learning_logs templates
learning_logs),
Django , -
. learning_logs
index.html. :
index.html
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
398 18 Django

. HTML, <p></p>
. <p> , </p> . -
: , ,
Learning Log.
URL- http://localhost:8000/
. Django
URL- , r'^$';
Django views.index(),
, index.html. -
.18.3.

. 18.3. Learning Log

, -
, URL-, -
. ,
,
. ,
, , - -
.


18-5. : .
meal_planner, -
Django. meal_plans. -
.
18-6. Pizzeria: Pizzeria,
18-4 (. 394).


, , -
Learning Log.
: , -
. URL,
399

. , ,
, .



. ,
;
.

.


base.html index.html.
, ;
base.html. , -
, .
,
:
base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>
{% block content %}{% endblock content %}

,
.
, % {% %}. -
, -
. {% url 'learning_logs:index' %}
URL-, URL, learning_logs/urls.
py 'index' . learning_logs ,
index URL .
HTML :
<a href="url_"> </a>

URL- -
. URL- ,
URL urls.py, Django URL-
.
base.html,
.
block . content
; , content,
.
400 18 Django

,
-
, ,
.

Python .
, Python,
.


index.html , base.html.
index.html :
index.htm
{% extends "learning_logs/base.html" %}

{% block content %}
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
{% endblock content %}

index.html, ,
Learning Log .
{% extends %},
Django, . base.html
learning_logs, learning_logs
. base.html
index.html , ,
content.
content {% block %} content.
, , content .
Learning Log.
, content , {% endblock
content %}.
, : -
, .
, .
, , -
.
, .
.

base.html -
.
base.html, . -
401

,
. -
.


, ,
:
. , -
, , .

URL
URL .
URL, , -
. topics,
URL http://localhost:8000/topics/. -
learning_logs/urls.py:
urls.py
""" URL learning_logs."""
...
urlpatterns = [
#
url(r'^$', views.index, name='index'),

# .
url(r'^topics/$', views.topics, name='topics'),
]

topics/ ,
URL- . Django
URL-, URL-, -
URL- topics. ,
, topics , -
. URL-, ,
topics() views.py.

topics
topics() -
. views.py :
views.py
from django.shortcuts import render

from .models import Topic

def index(request):
...
402 18 Django

def topics(request):
""" ."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)

, .
topics() : , Django
. Topic,
date_added. -
topics.
, .
, ,
, , -
. ,
, . -
, , render() context,
request .

topics
context, -
, topics(). topics.html
index.html. -
:
topics.html
{% extends "learning_logs/base.html" %}

{% block content %}

<p>Topics</p>

<ul>
{% for topic in topics %}
<li>{{ topic }}</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>

{% endblock content %}

{% extends %} base.html,
index, content.
(bulleted) . HTML -

<ul></ul>. .
, for -
context . , , -
Python . Python
403

, . for
{% endfor %}, . ,
:
{% for in %}

{% endfor %}

-
. ,
. {{ topic }} topic
. ;
Django . HTML
<li></li> . , ,
<ul></ul>, .
{% empty %}, Django,
. -
, . for
.

:
base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>

{% block content %}{% endblock content %}

, -
, .
Django ,
URL 'topics', learning_logs/urls.py.
, Topics.
, . 18.4.

. 18.4.
404 18 Django



, .
URL, . , -

.

URL
URL URL,
, id
. , -
Chess (id=1),
URL- http://localhost:8000/topics/1/.
URL- learning_logs/urls.py:
urls.py
...
urlpatterns = [
...
#
url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]

URL, r'^topics/(?P<topic_id>\d+)/$'.
r Django,
, .
, /(?P<topic_id>\d+)/, ,
; topic_id. -
, , URL;
?P<topic_id> topic_id; \d+
, .
Django URL-, , -
topic(), ,
topic_id. topic_id
.


topic()
:
views.py
--snip--
def topic(request, topic_id):
""" ."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
405

, ,
. , -
(?P<topic_id>\d+), topic_id . get()
( ,
Django). , , -
date_added: date_added
,
. context , -
topic.html.

, , -
. ,
Django. , -
, .


.
, :
topic.html
{% extends 'learning_logs/base.html' %}

{% block content %}

<p>Topic: {{ topic }}</p>

<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>
There are no entries for this topic yet.
</li>
{% endfor %}
</ul>

{% endblock content %}

base.html, .
{{ topic }}. topic -
, context.
; ,
.
406 18 Django

: -
.
date_added. Django (|)
, . date:'M d,
Y H:i' January 1, 2015 23:00.
text ( 50 -
). linebreaks ,
, ( ).
{% empty %} -
.


, -
, .
topics.html:
topics.html
...
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
...

URL
URL learning_logs 'topic'. URL
topic_id, URL topic.id.
,
http://localhost:8000/topics/1/.
, ,
. 18.5.

. 18.5.
407


18-7. : Django
https://docs.djangoproject.com/en/1.8/ref/templates/. -
.
18-8. Pizzeria: Pizzeria 18-6 (.398)
. , -
. ,
.

-
Django. , -
Django , , ,
. ,
. -
, , Django
.
,
.
Django,
. URL-,
-
. , ,
.
19 , ,
, -
. , -
,
. ,
- , -
.
19

-? , -
,
. , -
,
. , , Django -
,
.
. -
, ,
.
,
. ,
.



, ,
.
, , .
-
.
,
Django , .


.
, , : -
URL, .
forms.py,
.
409

ModelForm
, -
, , .
, ,
, (, -
).
. Django
.
Django
ModelForm, , -
18. forms.py,
models.py:
forms.py
from django import forms

from .models import Topic

class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}

forms , :
Topic. TopicForm, forms.
ModelForm . ModelForm Meta ,
Django,
. Topic,
text . Django -

.

URL- new_topic
URL- ,
, , -
http://localhost:8000/new_topic/. URL
new_topic, learning_logs/urls.py:
urls.py
...
urlpatterns = [
...
#
url(r'^new_topic/$', views.new_topic, name='new_topic'),
]

URL new_topic(),
.
410 19

new_topic()
new_topic() : -
new_topic ( )
, .
topics:
views.py
from django.shortcuts import render

from django.http import HttpResponseRedirect


from django.core.urlresolvers import reverse

from .models import Topic


from .forms import TopicForm

...
def new_topic(request):
""" ."""
if request.method != 'POST':
# ; .
form = TopicForm()
else:
# POST; .
form = TopicForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))

context = {'form': form}


return render(request, 'learning_logs/new_topic.html', context)

HttpResponseRedirect,
topics
. reverse() URL URL ( Django
URL ). -
TopicForm.

GET POST
-
GET POST. GET ,
, POST ,
.
POST ( -
, ).
new_topic() .
, GET.
,
POST. ,
411

( GET) (-
POST).
GET POST . -
POST, , GET,
( , -
). TopicForm , form -
context . TopicForm
, Django ,
.
POST, e l s e , -
, .
TopicForm , ,
request.POST. form , -
.
,
. is_valid() ,
( ), -
,
200, models.py 18. -
. ,
save() , -
. , . -
reverse() URL- topics
HttpResponseRedirect() ,
topics.
.

new_topic
new_topic.html
:
new_topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Add a new topic:</p>
<form action="{% url 'learning_logs:new_topic' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">add topic</button>
</form>

{% endblock content %}

base.html, ,
Learning Log. HTML.
action , , -
412 19

; new_topic().
method POST.
Django {% csrf_token %} -
(
). ;
, Django -
, .
, ,
{{ form.as_p }}. as_p Django -

.
Django ,
.

new_topic
new_topic topics:
topics.html
{% extends "learning_logs/base.html" %}

{% block content %}

<p>Topics</p>

<ul>
...
</ul>

<a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>

{% endblock content %}

. -
.19.1. .

. 19.1.
413


, , -
. URL,
. forms.py
.

EntryForm
, Entry, -
TopicForm:
forms.py
from django import forms

from .models import Topic, Entry

class TopicForm(forms.ModelForm):
...

class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
import Topic Entry. EntryForm -
forms.ModelForm Meta ,
, , . 'text' -
.
widgets. (widget) -
HTML: , -
.. widgets, ,
Django . Django forms.
Textarea, 'text',
80 40.
.

URL- new_entry
topic_id URL- ,
.
URL, learning_logs/urls.py:
urls.py
...
urlpatterns = [
...
#
url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
]
414 19

URL URL- http://


localhost:8000/new_entry/id/, id , .
(?P<topic_id>\d+)
topic_id. URL-,
, Django
new_entry().

new_entry()
new_entry
:
views.py
from django.shortcuts import render
...

from .models import Topic


from .forms import TopicForm, EntryForm

...
def new_entry(request, topic_id):
""" ."""
topic = Topic.objects.get(id=topic_id)

if request.method != 'POST':
# ; .
form = EntryForm()
else:
# POST; .
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic_id]))

context = {'topic': topic, 'form': form}


return render(request, 'learning_logs/new_entry.html', context)

import
EntryForm. new_entry() topic_id
URL. -
, topic_id
.
: POST GET. if
GET, EntryForm .
POST , EntryForm ,
POST .
. , topic
.
415

save() commit=False ,
new_entry, .
topic new_entry , -
, save() .
.
.
reverse() : URL,
URL-, ,
URL.
topic_id. HttpResponseRedirect() -
, ,
.

new_entry
, new_entry new_topic:
new_entry.html
{% extends "learning_logs/base.html" %}

{% block content %}

<p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>

<p>Add a new entry:</p>


<form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name='submit'>add entry</button>
</form>

{% endblock content %}

, ,
.
.
action topic_id URL,
.
new_topic.html.

new_entry
new_entry :
topic.html
{% extends "learning_logs/base.html" %}

{% block content %}

<p>Topic: {{ topic }}</p>


416 19

<p>Entries:</p>
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
</p>
<ul>
...
</ul>

{% endblock content %}

, -
. .19.2
new_entry.
. new_entry, -
.

. 19.2. new_entry


,
.

URL- edit_entry
URL-
. learning_logs/urls.py :
urls.py
...
urlpatterns = [
...
#
url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry,
name='edit_entry'),
]
417

, URL (, http://localhost:8000/edit_entry/1/),
entry_id. The URL , -
, edit_entry().

edit_entry()
edit_entry GET, edit_entry()
. POST
:
views.py
from django.shortcuts import render
...

from .models import Topic, Entry


from .forms import TopicForm, EntryForm
...

def edit_entry(request, entry_id):


""" ."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic

if request.method != 'POST':
# ; .
form = EntryForm(instance=entry)
else:
# POST; .
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic.id]))

context = {'entry': entry, 'topic': topic, 'form': form}


return render(request, 'learning_logs/edit_entry.html', context)

Entry.
, , , .
if, GET, EntryForm
instance=entry . Django ,
. -
.
POST i n s t a n c e = e n t r y
data=request.POST , Django
,
request.POST. .
, save() . -
, -
.
418 19

edit_entry
edit_entry.html new_entry.html:
edit_entry.html
{% extends "learning_logs/base.html" %}

{% block content %}

<p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>

<p>Edit entry:</p>

<form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>


{% csrf_token %}
{{ form.as_p }}
<button name="submit">save changes</button>
</form>

{% endblock content %}

action edit_entry() -
. {% url %} , -
.
, ,
, .

edit_entry
edit_entry
:
topic.html
...
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
<p>
<a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a>
</p>
</li>
...

. -
{% url %} URL
edit_entry (entry.id).
"edit entry" . .19.3 -
, .
Learning Log
. , -
.
419

. 19.3.

Learning Log .


19-1. : Django Blog. -
blogs BlogPost. , title,
text date_added. -
. ,
.

. , .


,
, -
. , ,
. Topic,
.

users
users startapp:
(ll_env)learning_log$ python manage.py startapp users
(ll_env)learning_log$ ls
420 19

db.sqlite3 learning_log learning_logs ll_env manage.py users


(ll_env)learning_log$ ls users
admin.py __init__.py migrations models.py tests.py views.py

users ,
learning_logs .

settings.py
settings.py:
settings.py
...
INSTALLED_APPS = (
...
# My apps
'learning_logs',
'users',
)
...

Django users .

URL- users
urls.py, URL-,
users:
urls.py
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^users/', include('users.urls', namespace='users')),
url(r'', include('learning_logs.urls', namespace='learning_logs')),
]

urls.py users. -
URL-, users, , http://
localhost:8000/users/login/. 'users',
URL-, learning_logs ,
URL, users.


. -
login, Django, URL
. urls.py learning_log/users/
:
urls.py
""" URL """
421

from django.conf.urls import url


from django.contrib.auth.views import login

from . import views

urlpatterns = [
#
url(r'^login/$', login, {'template_name': 'users/login.html'},
name='login'),
]

login .
URL http://localhost:8000/users/login/ . Django -
URL-, users , users/urls.py,
login , login
( : login,
views.login). ,
, Django, (
). users,
learning_logs.

login
, Django -
login ,
. learning_log/users/
templates, users.
login.html , learning_log/users/templates/
users/:

login.html
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

<form method="post" action="{% url 'users:login' %}">


{% csrf_token %}
{{ form.as_p }}

<button name="submit">log in</button>


<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>

{% endblock content %}

base.html,
. : -
.
422 19

errors, .
,
, .
, , action
URL . ,
.
'next'; value Django,
.
.


base.html,
. , -
, {% if %}:
base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a> -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>

{% block content %}{% endblock content %}

Django
user, is_authenticated:
True, , False . -

.
, .
username,

, .
, .


; ,
. http://localhost:8000/admin/.
,
.
http://localhost:8000/users/login/.
, .19.4.
, , .
423

. 19.4.

-
.

-
. ;
.
URL ,
base.html.

URL-
URL , URL
http://localhost:8000/users/logout/. users/urls.py :
urls.py
...
urlpatterns = [
#
...
#
url(r'^logout/$', views.logout_view, name='logout'),
]

URL logout_view(), ,
logout(), .
( , users/urls.py,
learning_log/urls.py.)

logout_view()
logout_view() : Django
logout(), , .
users/views.py :
424 19

views.py
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth import logout

def logout_view(request):
""" ."""
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))

logout() django.contrib.auth . -
logout() ,
. .


. base.html,
, {% if user.is_
authenticated %}, , -
:
base.html
...
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
...

. 19.5 , -
, . ,
. -
,
.

. 19.5.

425


.
Django UserCreationForm,
.

URL-
URL
users/urls.py:
urls.py
...
urlpatterns = [
#
...
#
url(r'^register/$', views.register, name='register'),
]

URL http://localhost:8000/users/register/ -
register(), .

register()
register()
,
. ,
. -
users/views.py:
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.forms import UserCreationForm

def logout_view(request):
...

def register(request):
""" ."""
if request.method != 'POST':
# Display blank registration form.
form = UserCreationForm()
else:
# .
form = UserCreationForm(data=request.POST)

if form.is_valid():
new_user = form.save()
# .
426 19

authenticated_user = authenticate(username=new_user.username,
password=request.POST['password1'])
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)

render(),
login() authenticate() , -
. UserCreationForm
. register() ,
POST. , UserCreationForm,
. POST UserCreationForm,
. , ;
,
, -
.
, save() -
. save()
,
new_user.
, ;
: authenticate()
new_user.username .
; ,
, , .
, 'password1' POST
. ,
, authenticated_user. -
login() request authenticated_user ,
.
, , -
, .


.
, login.html:
register.html
{% extends "learning_logs/base.html" %}

{% block content %}

<form method="post" action="{% url 'users:register' %}">


{% csrf_token %}
{{ form.as_p }}

<button name="submit">register</button>
427

<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />


</form>

{% endblock content %}

as_p, Django
, ,
.



, :
base.html
...
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
{% else %}
<a href="{% url 'users:register' %}">register</a> -
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
...

, ,
.
. ,
.
,
.
,
.

-
Learning Log. ,
, , .
, -
. , -
.


19-2. :
Blog, 19-1 (.419). ,
, , - , -
.
428 19


,
. , ,
, , -
.
Topic, -
. -
, .
.

@login_required
Django -
, , @login_required.
(decorator) ,
, -
. .


, -
.
learning_logs/views.py:
views.py
...
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from .models import Topic, Entry


...

@login_required
def topics(request):
""" ."""
...

login_required() . login_
required() topics(),
login_required() @; Python,
topics().
login_required() , , Django -
topics() .
, .
, settings.py -
Django, .
settings.py:
429

settings.py
"""
Django settings for learning_log project
...

#
LOGIN_URL = '/users/login/'

, , ,
@login_required, Django URL-,
LOGIN_URL settings.py.
,
. Topics,
. -
, Topics.
.

Learning Log
Django , ,
. ,
,
. , -
, .
Learning Log
, .
.
learning_logs/views.py @login_required, -
, index():
views.py
...
@login_required
def topics(request):
...

@login_required
def topic(request, topic_id):
...

@login_required
def new_topic(request):
...

@login_required
def new_entry(request, topic_id):
...

@login_required
def edit_entry(request, entry_id):
...
430 19

: -
. ,
, new_topic. URL http://localhost:8000/new_topic/,
. URL-,
.


, , -
, . ,
,
. , Learning Log
, .
,
.
Topic .
. ,
, ,
.

Topic
models.py :
models.py
from django.db import models
from django.contrib.auth.models import User

class Topic(models.Model):
""", """
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)

def __str__(self):
""" ."""
return self.text

class Entry(models.Model):
...

User django.contrib.auth. Topic -


owner, User.


Django , -
.
Django ,
. -
431

, .
.
, -
. Django :
(venv)learning_log$ python manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.all()
[<User: ll_admin>, <User: eric>, <User: willie>]
>>> for user in User.objects.all():
... print(user.username, user.id)
...
ll_admin 1
eric 2
willie 3
>>>

User. -
, .
: ll_admin, eric willie.
, -
. Django ,
, .


, .
(venv)learning_log$ python manage.py makemigrations learning_logs
You are trying to add a non-nullable field 'owner' to topic without a default;
we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do
e.g. timezone.now()
>>> 1
Migrations for 'learning_logs':
0003_topic_owner.py:
- Add field owner to topic

makemigrations . Django -
, (
null) (topic) .
Django : -
,
models.py. . Django
.
-
ll_admin, 1.
432 19

;
. Django ,
, 0003_topic_owner.py, owner
Topic.
. -
:
(venv)learning_log$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: learning_logs, contenttypes, sessions, admin, auth
...
Running migrations:
Rendering model states... DONE
Applying learning_logs.0003_topic_owner... OK
(venv)learning_log$

Django OK . ,
, ,
:
>>> from learning_logs.models import Topic
>>> for topic in Topic.objects.all():
... print(topic, topic.owner)
...
Chess ll_admin
Rock Climbing ll_admin
>>>

Topic learning_logs.models -
, , -
. , ll_admin.

,
. -
. , -
python manage.py flush .
, .


, , -
, . -
, .
topics() views.py:
views.py
...
@login_required
433

def topics(request):
""" ."""
topics = Topic.objects.filter(owner=request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
...

,
request.user . Topic.objects.
filter(owner=request.user) Django
Topic, owner .
,
.
, , ,
,
. .
. .


, -
URL
(, http://localhost:8000/topics/1/) ,
.
. -
URL URL ,
. URL .
,
.
,
topic():
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
...

@login_required
def topic(request, topic_id):
""" ."""
topic = Topic.objects.get(id=topic_id)
# , .
if topic.owner != request.user:
raise Http404

entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
...
434 19

404 , ,
. -
Http404 ,
, . ,
,
. -
, Http404 , Django 404.
Django
. 20 ,
.

edit_entry
edit_entry URL- http://localhost:8000/edit_
entry/entry_id/, entry_id . ,
URL :
views.py
...
@login_required
def edit_entry(request, entry_id):
""" ."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if topic.owner != request.user:
raise Http404

if request.method != 'POST':
# ; .
...

, . ,
;
Http404.


,
.
IntegrityError learning_
logs_topic.user_id may not be NULL. Django ,
owner.
,
request. , -
:
views.py
...
435

@login_required
def new_topic(request):
""" ."""
if request.method != 'POST':
# ; .
form = TopicForm()
else:
# POST; .
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))

context = {'form': form}


return render(request, 'learning_logs/new_topic.html', context)
...

form.save() commit=False,
.
owner . ,
save() .
, .

.
, : ,
.


19-3. : views.py , , -
, , .
check_topic_owner() .
19-4. new_entry:
, URL- , -
. ,
, , -
.
19-5. : Blog ,
. , -
,
. ,
, , -
.

-
, . -
. -
436 19

,
Django UserCreationForm
.

; -
@login_required.
. ,
,
.
, , -
, . -
filter(),
.
, -
, , .
, ,
, :
- ,
.
, -
.
Learning Log, . -
,
.
20

Learning Log ,
.
, ,
, .
Bootstrap
-,
, -
. django-
bootstrap3, ,
Django.
Learning Log Heroku , -
,
.
Git
.
Learning Log , -
-,
. -
.

Learning Log
, -
. ,
, .
, ,
, .
django-bootstrap3 , -
.
438 20

django-bootstrap3
Bootstrap django-
bootstrap3. Bootstrap,

.
django-bootstrap3,
:
(ll_env)learning_log$ pip install django-bootstrap3
...
Successfully installed django-bootstrap3
django-boostrap3
INSTALLED_APPS settings.py:
settings.py
...
INSTALLED_APPS = (
...
'django.contrib.staticfiles',

#
'bootstrap3',

#
'learning_logs',
'users',
)
...

, ,
'bootstrap3'.
INSTALLED_APPS, -
.
django-bootstrap3 jQuery JavaScript,
, -
Bootstrap. settings.py:
settings.py
...
#
LOGIN_URL = '/users/login/'

# django-bootstrap3
BOOTSTRAP3 = {
'include_jquery': True,
}

jQuery -
.
Learning Log 439

Bootstrap Learning Log


Bootstrap
. , -
.
Bootstrap, -
, .
, Bootstrap, Getting Started
http://getbootstrap.com/; Examples
Navbars in action. Static top navbar,
,
.
.20.1 ,
Bootstrap base.html index.html.

. 20.1. Learning Log

, ,
.

base.html
base.html ,
Bootstrap. base.html .
440 20

HTML
base.html: HTML ,
Learning Log
. Bootstrap
. base.html :
base.html
{% load bootstrap3 %}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Learning Log</title>

{% bootstrap_css %}
{% bootstrap_javascript %}

</head>

django-bootstrap3.
HTML , .
HTML , -
. HTML :
,
. title ;
Learning Log.
django-bootstrap3,
Django Bootstrap.
, , -
, .
</head>.


:
...
</head>

<body>
<!-- -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">

<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
Learning Log 441

</button>
<a class="navbar-brand" href="{% url 'learning_logs:index' %}">
Learning Log</a>
</div>

<div id="navbar" class="navbar-collapse collapse">


<ul class="nav navbar-nav">
<li><a href="{% url 'learning_logs:topics' %}">Topics</a></li>
</ul>

<ul class="nav navbar-nav navbar-right">


{% if user.is_authenticated %}
<li><a>Hello, {{ user.username }}.</a></li>
<li><a href="{% url 'users:logout' %}">log out</a></li>
{% else %}
<li><a href="{% url 'users:register' %}">register</a></li>
<li><a href="{% url 'users:login' %}">log in</a></li>
{% endif %}
</ul>
</div><!--/.nav-collapse -->

</div>
</nav>

<body>. HTML -
, . <nav>
.
Bootstrap, navbar,
navbar-default navbar-static-top. ,
.
, ,

. ,
. collapse

.
.
,
.
.
, <ul> ,
(<li>) . ,
:
<li><a href="{% url 'learning_logs: %}"></a></li>
.
base.html.
, -
navbar-right. navbar-right
442 20

, , -
/ .
, -
. ,
.


base.html :
...
</nav>

<div class="container">
<div class="page-header">
{% block header %}{% endblock header %}
</div>
<div>
{% block content %}{% endblock content %}
</div>

</div> <!-- /container -->

</body>
</html>

div container. div -


,
, (),
(),
. div -
: header
content, 18 . header ,
.
page-header,
. content div
.
Learning Log , -
, . 20.1. -
, ;
. ,
.

Bootstrap -
. . ,
http://getbootstrap.com/getting-started/#examples/,
.
Learning Log 443


header
Bootstrap, (jumbotron) ,
-
.
. ,
. index.html :
index.html
{% extends "learning_logs/base.html" %}

{% block header %}
<div class='jumbotron'>
<h1>Track your learning.</h1>
</div>
{% endblock header %}

{% block content %}
<h2>
<a href="{% url 'users:register' %}">Register an account</a> to make
your own Learning Log, and list the topics you're learning about.
</h2>
<h2>
Whenever you learn something new about a topic, make an entry
summarizing what you've learned.
</h2>
{% endblock content %}

Django ,
header. jumbotron Track your
learning, , Learning Log.
,
. , -

. . 20.1 ,
.


,
.
:
login.html
{% extends "learning_logs/base.html" %}
{% load bootstrap3 %}

{% block header %}
<h2>Log in to your account.</h2>
444 20

{% endblock header %}

{% block content %}

<form method="post" action="{% url 'users:login' %}" class="form">


{% csrf_token %}
{% bootstrap_form form %}

{% buttons %}
<button name="submit" class="btn btn-primary">log in</button>
{% endbuttons %}

<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />


</form>

{% endblock content %}

bootstrap3. -
header, , . -
: {% if form.errors %} ; django-bootstrap3
.
class="form",
{% bootstrap_form %}; {{ form.as_p }},
19. {% booststrap_form %}
Bootstrap . -
bootstrap3 {% buttons %},
Bootstrap .
. 20.2 , . -
, , .

. 20.2. , Bootstrap
Learning Log 445

;
,
.

new_topic
.
new_topic:
new_topic.html
{% extends "learning_logs/base.html" %}
{% load bootstrap3 %}

{% block header %}
<h2>Add a new topic:</h2>
{% endblock header %}

{% block content %}

<form action="{% url 'learning_logs:new_topic' %}" method='post'


class="form">

{% csrf_token %}
{% bootstrap_form form %}

{% buttons %}
<button name="submit" class="btn btn-primary">add topic</button>
{% endbuttons %}

</form>

{% endblock content %}

, login.html:
bootstrap3 header -
. <form> class="form" , {{ form.as_p }}
{% bootstrap_form %} , -
bootstrap3 . new_topic;
.


,
. :
topics.html
{% extends "learning_logs/base.html" %}

{% block header %}
<h1>Topics</h1>
{% endblock header %}
446 20

{% block content %}

<ul>
{% for topic in topics %}
<li>
<h3>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</h3>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>

<h3><a href="{% url 'learning_logs:new_topic' %}">Add new topic</h3>

{% endblock content %}

{% load bootstrap3 %} , -
bootstrap3. Topics header.
<h3>,
;
.


, ,
. , -
Bootstrap. div
:
topic.html
{% extends 'learning_logs/base.html' %}

{% block header %}
<h2>{{ topic }}</h2>
{% endblock header %}

{% block content %}
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
</p>

{% for entry in entries %}


<div class="panel panel-default">
<div class="panel-heading">
<h3>
{{ entry.date_added|date:'M d, Y H:i' }}
<small>
<a href="{% url 'learning_logs:edit_entry' entry.id %}">
edit entry</a>
Learning Log 447

</small>
</h3>
</div>
<div class="panel-body">
{{ entry.text|linebreaks }}
</div>
</div> <!-- panel -->
{% empty %}
There are no entries for this topic yet.
{% endfor %}

{% endblock content %}

header . -
, .
, div
, div: panel-heading
panel-body . div panel-heading
. <h3>,
edit_entry <small>,
.
div panel-body,
. : Django -
; ,
.

. 20.3. Bootstrap
448 20

. 20.3 .
Learning Log , -
.

Bootstrap, -
, . base.html
, , .
Bootstrap
.


20-1. : Bootstrap login add_topic.
: new_entry, edit_entry register.
20-2. Blog: Bootstrap
Blog 19.

Learning Log
,
,
. Heroku -, -
-.
Windows Linux OS X.
Windows, , ,
.

Heroku
, https://heroku.com/
. ,
Heroku -
.

Heroku (, ,
, ). , -
,
- .

Heroku Toolbelt
Heroku , -
Heroku Toolbelt. Heroku
Toolbelt, https://toolbelt.heroku.com/
Learning Log 449

. -
, , .


,
Django .
:
(ll_env)learning_log$ pip install dj-database-url
(ll_env)learning_log$ pip install dj-static
(ll_env)learning_log$ pip install static3
(ll_env)learning_log$ pip install gunicorn

, , -
- . dj-database-url Django -
, Heroku, dj-static static3
Django , gunicorn -
, . (-
JavaScript.)

Windows, ,
. ,
Heroku , .

requirements.txt
Heroku , , -
pip . -
, :
(ll_env)learning_log$ pip freeze > requirements.txt
freeze pip ,
, requirements.txt. requirements.txt
, (,
Windows - ):
requirements.txt
Django==1.8.4
dj-database-url==0.3.0
dj-static==0.0.6
django-bootstrap3==6.2.2
gunicorn==19.3.0
static3==0.6.1

Learning Log
, -
. Learning Log Heroku -
450 20

, requirements.txt, ,
. ,
, .
, ,
.
psycopg2, Heroku
. requirements.txt
psycopg2>=2.6.1. 2.6.1 psycopg2 (
, ):
requirements.txt
Django==1.8.4
dj-database-url==0.3.0
dj-static==0.0.6
django-bootstrap3==6.2.2
gunicorn==19.3.0
static3==0.6.1
psycopg2>=2.6.1

- , .
requirements.txt .
, ,
.

Windows, , requirements.txt -
, ,
.

Python
Python, Heroku
Python . , Heroku -
Python, .
python --version:
(ll_env)learning_log$ python --version
Python 3.5.0

Python 3.5.0. runtime.


txt manage.py :

runtime.txt
python-3.5.0

Python, -
: python ,
.
Learning Log 451

, ,
Python , https://devcenter.heroku.com/
Python, Specifying a Python Runtime. , -
,
Python.

settings.py Heroku
settings.py -
, Heroku:
settings.py
...
# django-bootstrap3
BOOTSTRAP3 = {
'include_jquery': True,
}

# Heroku
if os.getcwd() == '/app':
import dj_database_url
DATABASES = {
'default': dj_database_url.config(default='postgres://localhost')
}

# 'X-Forwarded-Proto' request.is_secure().
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# .
ALLOWED_HOSTS = ['*']

#
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'staticfiles'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)

getcwd(),
, . Heroku
/app.
(learning_log ). if
, -
Heroku. ,
,
.
dj_database_url,
Heroku. Heroku PostgreSQL ( Postgres) -
, SQLite;
Postgres Heroku.
452 20

HTTPS, URL Heroku -


Heroku .

Procfile
Procfile Heroku, -
. ,
Procfile ( P , )
manage.py. Procfile :
Procfile
web: gunicorn learning_log.wsgi --log-file -

Heroku gunicorn,
learning_log/wsgi.py.
log-file Heroku, -
.

wsgi.py Heroku
wsgi.py Heroku,
Heroku ,
:
wsgi.py
...
import os

from django.core.wsgi import get_wsgi_application


from dj_static import Cling

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "learning_log.settings")
application = Cling(get_wsgi_application())

Cling, -
, .
, if .


Heroku Django
.
. learning_log, ,
learning_log.
static; , learning_log/
learning_log/static/. -
, Heroku
. static/ placeholder.txt:
Learning Log 453

placeholder.txt
learning_log/static/.
Django learning_log/static/.

; ,
.

gunicorn
Linux OS X,
gunicorn , Heroku.
heroku local, ,
Procfile:
(ll_env)learning_log$ heroku local
Installing Heroku Toolbelt v4... done
...
forego | starting web.1 on port 5000
web.1 | [2015-08-13 22:00:45 -0800] [12875] [INFO] Starting gunicorn 19.3.0
web.1 | [2015-08-13 22:00:45 -0800] [12875] [INFO] Listening at:
http://0.0.0.0:5000 (12875)
web.1 | [2015-08-13 22:00:45 -0800] [12878] [INFO] Booting worker with pid:
12878

heroku local Heroku


Toolbelt. , gunicorn
12875 . gunicorn -
5000. , gunicorn
(12878), .
http://localhost:5000/ , ;
Learning Log , -
Django (runserver). Ctrl+C, ,
heroku local. -
runserver.

Windows gunicorn ; , Windows.


Heroku.

Git
17, , Git
, -
.
-
(,
).
454 20

Git, ,
, , . -
, ,
. Git
, .

Git
Git Heroku Toolbelt, Git
. Git
, Heroku Toolbelt,
git --version:
(ll_env)learning_log$ git --version
git version 2.5.0

,
Git .

Git
Git , , , -
. Git
. ,
-
:
(ll_env)learning_log$ git config --global user.name "ehmatthes"
(ll_env)learning_log$ git config --global user.email "eric@example.com"

, Git
.


, Git ,
Git . .gitignore
manage.py. : ,
. .gitignore :
.gitignore
ll_env/
__pycache__/
*.sqlite3

Git ll_env, -
. -
__pycache__ .pyc, ,
Django .py.
, : -
Learning Log 455

SQLite,
.

Python 2.7, __pycache__ *.pyc, Python 2.7


__pycache__.


Git Learning Log, -
.
:
(ll_env)learning_log$ git init
Initialized empty Git repository in /home/ehmatthes/pcc/learning_log/.git/
(ll_env)learning_log$ git add .
(ll_env)learning_log$ git commit -am "Ready for deployment to heroku."
[master (root-commit) dbc1d99] Ready for deployment to heroku.
43 files changed, 746 insertions(+)
create mode 100644 .gitignore
create mode 100644 Procfile
--snip--
create mode 100644 users/views.py
(ll_env)learning_log$ git status
# On branch master
nothing to commit, working directory clean
(ll_env)learning_log$

git init, -
, Learning Log. git add.
( ) ( ).
git commit -am : -a Git
, -m Git
.
git status , , -
. ,
Heroku.


- Heroku. -
:
(ll_env)learning_log$ heroku login
Enter your Heroku credentials.
Email: eric@example.com
Password (typing will be hidden):
Logged in as eric@example.com
(ll_env)learning_log$ heroku create
Creating afternoon-meadow-2775... done, stack is cedar-14
https://afternoon-meadow-2775.herokuapp.com/ |
456 20

https://git.heroku.com/afternoon-meadow-2775.git
Git remote heroku added
(ll_env)learning_log$ git push heroku master
...
remote: -----> Launching... done, v6
remote: https://afternoon-meadow-2775.herokuapp.com/ deployed to Heroku
remote: Verifying deploy.... done.
To https://git.heroku.com/afternoon-meadow-2775.git
bdb2a35..62d711d master -> master
(ll_env)learning_log$

Heroku
, https://heroku.com/.
Heroku . Heroku , -
; .
git push heroku master , Git
, Heroku. Heroku
. -
URL, .
, .
, ,
heroku ps:
(ll_env)learning_log$ heroku ps
Free quota left: 17h 40m
=== web (Free): `gunicorn learning_log.wsgi __log-file -`
web.1: up 2015/08/14 07:08:51 (~ 10m ago)
(ll_env)learning_log$

, -
24 . Heroku
18
24- .
; . ,
Procfile.
heroku open:
(ll_env)learning_log$ heroku open
Opening afternoon-meadow-2775... done

URL,
Heroku, .
Learning Log . ,
, .

Heroku .
, Heroku .
https://devcenter.heroku.com/ Python, Getting
Started with Django. , ,
.
Learning Log 457

Heroku
migrate, -
, .
Django Python Heroku heroku run. -
migrate Heroku:
(ll_env)learning_log$ heroku run python manage.py migrate
Running `python manage.py migrate` on afternoon-meadow-2775... up, run.2435
...
Running migrations:
...
Applying learning_logs.0001_initial... OK
Applying learning_logs.0002_entry... OK
Applying learning_logs.0003_topic_user... OK
Applying sessions.0001_initial... OK
(ll_env)learning_log$

heroku run python manage.py migrate . Heroku -


migrate . Django
, ,
Learning Log.

, . -
, , -
. :
, .
Heroku, -
Learning Log.
,
Learning Log.


-
( , ). -
, DEBUG
False,
, .

Heroku
,
heroku run . , -
Bash Heroku heroku run bash.
Bash , Linux. -
Bash ,
:
458 20

(ll_env)learning_log$ heroku run bash


Running `bash` on afternoon-meadow-2775... up, run.6244
~ $ ls
learning_log learning_logs manage.py Procfile requirements.txt runtime.txt
users
staticfiles
~ $ python manage.py createsuperuser
Username (leave blank to use 'u41907'): ll_admin
Email address:
Password:
Password (again):
Superuser created successfully.
~ $ exit
exit
(ll_env)learning_log$

ls ,
; , .
, .

Windows (, ls dir),
Linux .
.
, -
18.
, exit
.
/admin/ URL- ,
. URL- https://
afternoon-meadow-2775.herokuapp.com/admin/.
, ,
! ,
.

URL- Heroku
, URL-
, https://afternoon-meadow-2775.herokuapp.com/.
, :
(ll_env)learning_log$ heroku apps:rename learning-log
Renaming afternoon-meadow-2775 to learning-log... done
https://learning-log.herokuapp.com/ | https://git.heroku.com/learning-log.git
Git remote heroku updated
(ll_env)learning_log$

, ( ,
).
https://learning-log.herokuapp.com/. URL- -
; apps:rename URL-.
Learning Log 459

Heroku
,
.
,
. Heroku .


-
: DEBUG=True settings.py,
. Django
,
,
. , -
, .
settings.py, ,
:
settings.py
...
# Heroku
if os.getcwd() == '/app':
...
# 'X-Forwarded-Proto' request.is_secure().
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Heroku.
ALLOWED_HOSTS = ['learning-log.herokuapp.com']

DEBUG = False

# .
...

:
ALLOWED_HOSTS, Heroku.
Heroku ( afternoon-meadow-2775.
herokuapp.com ) . DEBUG
False,
.


, settings.py,
Git, Heroku. ,
:
(ll_env)learning_log$ git commit -am "Set DEBUG=False for Heroku."
[master 081f635] Set DEBUG=False for Heroku.
460 20

1 file changed, 4 insertions(+), 2 deletions(-)


(ll_env)learning_log$ git status
# On branch master
nothing to commit, working directory clean
(ll_env)learning_log$

git commit , .
, -am
. Git , , -
.
,
, . -
Heroku.
, , , -
. commit,
, , , ,
Git.
Heroku:
(ll_env)learning_log$ git push heroku master
...
remote: -----> Python app detected
remote: -----> Installing dependencies with pip
...
remote: -----> Launching... done, v8
remote: https://learning-log.herokuapp.com/ deployed to Heroku
remote: Verifying deploy.... done.
To https://git.heroku.com/learning-log.git
4c9d111..ef65d2b master -> master
(ll_env)learning_log$

Heroku , , , -
. ,
migrate .
, , URL
, . ,
http://learning-log.herokuapp.com/letmein/.
,
.
Learning Log http://localhost:8000/letmein/,
Django. , :
,
.


19 Learning Log ,
, , 404. -
Learning Log 461

, 500 ( ).
404 , Django ,
; 500 ,
(, views.py).
Django ,
404 500, -
Learning Log.
.


learning_log/learning_log templates.
404.html:
404.html
{% extends "learning_logs/base.html" %}
{% block header %}
<h2>The item you requested is not available. (404)</h2>
{% endblock header %}

, -
404, .
500.html:
500.html
{% extends "learning_logs/base.html" %}

{% block header %}
<h2>There has been an internal error. (500)</h2>
{% endblock header %}

settings.py.
settings.py
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'learning_log/templates')],
'APP_DIRS': True,
...
},
]
...

Django
.


, ,
Heroku,
462 20

Debug=False, Django
. settings.py (
, settings.py, ,
, Heroku):
settings.py
...
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = ['localhost']
...

DEBUG False, ALLOWED_HOSTS


. , ,
404. URL- (-
, localhost:8000/letmein/), 500.
, DEBUG True,
Learning Log. ( , DEBUG False
settings.py, Heroku.)

500 ,
Django .

Heroku
Heroku:
(ll_env)learning_log$ git add .
(ll_env)learning_log$ git commit -am "Added custom 404 and 500 error pages."
3 files changed, 15 insertions(+), 10 deletions(-)
create mode 100644 learning_log/templates/404.html
create mode 100644 learning_log/templates/500.html
(ll_env)learning_log$ git push heroku master
...
remote: Verifying deploy.... done.
To https://git.heroku.com/learning-log.git
2b34ca1..a64d8d3 master -> master
(ll_env)learning_log$

git add .,
, Git .
Heroku .
, ,
.

get_object_or_404()
,
, 500. Django
Learning Log 463

, ,
500. 404,
Django
get_object_or_404().
, 404. -
views.py get():
views.py
...
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, Http404
...
@login_required
def topic(request, topic_id):
""" ."""
topic = get_object_or_404(Topic, id=topic_id)
# , .
...

(, http://localhost:8000/
topics/999999/) 404. -
, Heroku.


, Learning Log -
. -
.
. -
, Git
git add . ( ).
, ,
.
git commit -am "".
Heroku git push heroku master.
,
.
heroku run python manage.py migrate,
heroku run bash python manage.py migrate.
,
.
, , -
. , , , -
. ,
, .
:
, , -,
464 20

.
, ,
.

SECRET_KEY
Django SECRET_KEY settings.py -
.
SECRET_KEY. -
, SECRET_KEY
. , ,
, SECRET_KEY.

Heroku
-
, .
, . Heroku
,
. - Heroku
(https://heroku.com/), -
. , ;
. Settings, -
. , Heroku
,
. ,
destroy:
(ll_env)learning_log$ heroku apps:destroy --app _

_ (, afternoon-meadow-2775
learning-log, ).
, .

Heroku .
,
Heroku .


20-3. : Blog, , -
Heroku. , DEBUG False,
ALLOWED_HOSTS, .
20-4. 404: get_object_or_404() -
new_entry() edit_entry(). , URL-
http://localhost:8000/new_entry/99999/ ,
404.
465

20-5. Learning Log: Learning Log


(, )
.
, .
Topic public ( False),
new_topic , -
. views.py, -
,
.
Heroku.

, , -
Bootstrap django-
bootstrap3. Bootstrap
,
.
Bootstrap Static top navbar -
Learning Log.
jumbotron ,
.
, Heroku,
. Heroku
, .
Git
Heroku. , , ,
DEBUG=False .
, Learning Log , -
. , -
, .
!
.
Python

Python , -
.
, 1
Python , .

Python Linux
Python Linux, ,
. ,
Python .


:
$ python --version
Python 2.7.6

, 2.7.6.
, Python 3.
:
$ python3 --version
Python 3.5.0

, Python 3.5.0 .
, .

Python 3 Linux
Python 3
Python 3, .
deadsnakes, Python:
$ sudo add-apt-repository ppa:fkrull/deadsnakes
$ sudo apt-get update
$ sudo apt-get install python3.5

Python 3.5 .
Python 3.5:
Python os x 467

$ python3.5
>>>


Python 3 .

Python OS X
Python OS X, , -
. ,
Python .


:
$ python --version
Python 2.7.6

python3 --version. ,
, ,
.

Homebrew Python 3
Python 2 Python 3, -
Python 3 Homebrew.

Homebrew
Homebrew Apple Xcode,
:
$ xcode-select --install

(
).
Homebrew:
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/
master/install)"

Homebrew
http://brew.sh/. curl -fsSL URL-.

-e Ruby ( , -
Homebrew) .
.
, Homebrew ,
:
468 . Python

$ brew doctor
Your system is ready to brew.

, Python
Homebrew.

Python 3
Python 3, :
$ brew install python3

:
$ python3 --version
Python 3.5.0
$

c Python 3 python3,
python3 ,
Python Python 3 Python 2.

Python Windows
Python Windows ,
, Python .
, Shift,
Open Command Window Here .
(Start). :
> python --version
Python 3.5.0

, , Python
( , , ).
, Python.

Python 3 Windows
http://python.org/downloads/
Python. ,
Add Python to PATH. ,
python python,
.
Python, python --version . -
, , .
Python
python , Windows, -
Python. , C
, Python ( python
Windows). -
Python 469

python .
(Properties);
(Location).
:
$ C:\\Python35\python --version
Python 3.5.0

Python PATH
, Python,
, ,
python. Add
Python to PATH , .
, (System and
Security), (System).
(Advanced System Settings).
(Environment Variables).
(System variables) Path.
Edit. Variable value
. -
; ,
Cancel . python.exe
:
%SystemRoot%\system32\...\System32\WindowsPowerShell\v1.0\;C:\Python34
.
Path . python
--version Python, -
Path. Python,
python .

Python
Python . ,
.
, -
. Python,
Python, .
Python ,
, .

Python
-
Python.
.
470 . Python

False class finally is return


None continue for lambda try
True def from nonlocal while
and del global not with
as elif if or yield
assert else import pass
break except in raise

Python

, , :

abs() divmod() input() open() staticmethod()

all() enumerate() int() ord() str()

any() eval() isinstance() pow() sum()

basestring() execfile() issubclass() print() super()

bin() file() iter() property() tuple()

bool() filter() len() range() type()

bytearray() float() list() raw_input() unichr()

callable() format() locals() reduce() unicode()

chr() frozenset() long() reload() vars()

classmethod() getattr() map() repr() xrange()

cmp() globals() max() reversed() zip()

compile() hasattr() memoryview() round() __import__()

complex() hash() min() set() apply()

delattr() help() next() setattr() buffer()

dict() hex() object() slice() coerce()

dir() id() oct() sorted() intern()

Python 2.7 print , . , Python 3


unicode() . -
.
.

, -
. ,
. -
,
. -
,
.
,
, .
- , ,
.
:
Geany , Linux Windows, Sublime Text OS X
( Linux Windows).
IDLE, , Python . ,
Emacs vim ,
, .
hello_world.py
.

Geany
Geany ,
. , Geany -
, .

Geany Linux
Linux Geany :
$ sudo apt-get install geany

Python,
Geany . Geany,
FileSave As hello_world.py.
:
print("Hello Python world!")
472 .

BuildSet Build Commands . Compile


Execute, . Geany -
, python,
python3, .
Compile :
python3 -m py_compile "%f"

. -
.
Execute :
python3 "%f"

Geany Windows
Geany Windows
http://geany.org/. Releases Download
geany-1.25_setup.exe ( - ). -
.
Geany, FileSave As -
hello_world.py. :
print("Hello Python world!")

BuildSet Build Commands. Compile Execute,


. -
python ( ), Geany , -
python.
. ( , Path
, .)
Compile Execute , -
python. Compile :
C:\Python35\python -m py_compile "%f"

, , -
, .
Execute :
C:\Python35\python "%f"

. -
, OK.
.
Geany 473

Python Geany
Geany. hello_world.py,
BuildExecute,
F5. hello_world.py
:
Hello Python world!

------------------
(program exited with code: 0)
Press return to continue

Geany
Geany, -
. , .



Python. Geany,
EditPreferencesEditorIndentation. 4
Type Spaces.
, -
DocumentReplace Tabs by Spaces.



( ), . -
, EditPreferencesEditorDisplay,
, Long line . ,
Column 79.


,
EditFormatIncrease Indent Ctrl+I. , -
EditFormatDecrease Indent Ctrl+U.


,
, Python . -
EditFormatToggle Line Commentation (Ctrl+E).
(#~), , -
. ,
.
474 .

Sublime Text
Sublime Text ,
OS X ( ) -
.
, Sublime Text, .
Sublime Text :
,
, -
. Sublime Text 3
.

Sublime Text OS X
Sublime Text http://www.sublimetext.com/3.
OS X.
, Sublime Text -
Applications.

Sublime Text Linux


Linux Sublime Text
:
$ sudo add-apt-repository ppa:webupd8team/sublime-text-3
$ sudo apt-get update
$ sudo apt-get install sublime-text-installer

Sublime Text Windows


Windows http://www.sublimetext.
com/3. , Sublime Text
.

Python Sublime Text


Python, , -
, - .
, ToolsBuild Ctrl+B.
hello_world.py, Sublime Text

Hello Python world!
[Finished in 0.1s]
Sublime Text 475

Sublime Text
Python Sublime Text
Python ,
. Python.
Linux OS X :
$ type -a python3
python3 is /usr/local/bin/python3

python3 , -
.
Windows, Python3
Windows . 466, ,
Python.
Sublime Text ToolsBuild SystemNew Build
System, . -
:
Python3.sublime-build
{
"cmd": ["/usr/local/bin/python3", "-u", "$file"],
}

Sublime Text python3


. , , -
( Windows C:/Python35/python -
). Python3.sublime-build -
, Sublime Text Save.
hello_world.py, ToolsBuild SystemPython3,
ToolsBuild. ,
Sublime Text.

Sublime Text
Sublime Text,
. , -
.


ViewIndentation , Indent Using
Spaces . , .


ViewRuler 80. Sublime Text -
80- .
476 .


, EditLineIndent
Ctrl+] . ,
EditLineUnindent Ctrl+[.

IDLE
IDLE Python. , Geany
Sublime Text, ,
, .

IDLE Linux
Python 3, idle3 :
$ sudo apt-get install idle3
Python 2, idle :
$ sudo apt-get install idle

IDLE OS X
Homebrew Python, ,
IDLE . brew
linkapps, IDLE, Python
. IDLE
.
https://www.python.org/download/mac/
tcltk/ ; -
, IDLE.

IDLE Windows
IDLE ,
Python. .

IDLE
IDLE Python ,
IDLE Python:
,
80 .


, FormatIndent
Region Ctrl+] . ,
FormatDedent Region Ctrl+[.
Emacs vim 477


, -
FormatComment out Region Alt+3. ,
FormatUncomment Region Alt+4.

Emacs vim
emacs vim. -
, -
. , ,
. ,
.
, -
, . -
, ,

, ,
.
.

- -
. , -
, .
,
.


, . -
, ,
:
?
?
?
. ,

Python3 Windows 10 , -
Python .
Python , -
.
, -
, : http://
python.org/downloads/ Download Python 3.
, Python
.
, -
.
,
, .
:
. (
) ,
.
, .
479


; -
. , for
. , -
, .
.


- ,
, . -
, .
,
. ,
-, .
, - : -
; , -
.
, .
.


(https://www.nostarch.com/pythoncrashcourse/)
, -
. , ,
.


, -
.
. , -
Python 3 Windows 10, python 3 windows 10
.

. , Python -
:
> python
'python' is not recognized as an internal or external command
>

, .
, , -
. , ,
.
480 .

Stack Overflow
Stack Overflow (http://stackoverlow.com/), -
,
, Python.
, .
, , ,
,
.
Stack Overflow -
Python, .
, .
Stack Overflow
400000 , Python.

Python
Python (http://docs.python.org/) -
, ,
. ,
, - .
, , -
Python .


(, Pygame, matplotlib,
Django ..), -
, http://docs.djangoproject.com/
. ,
.

r/learnpython
Reddit (subreddits). r/learnpython
(http://reddit.com/r/learnpython/) .

.


,
. ,
. ,
. , -
.
IRC (Internet Relay Chat) 481

IRC (Internet Relay Chat)


IRC. -
, , IRC
. , ,
, , -
, .

IRC
IRC, http://webchat.freenode.net/.
, c (captcha) -
Connect. , IRC
freenode. :
/msg nickserv register __

. , -
.
, .

. :
/msg nickserv verify register _

IRC , , -
. .


Python, /join #python.
, ,
.
##learnpython ( #) .
http://reddit.com/r/learnpython/,
r/learnpython. #pyladies
, Python, , -
. -,
#django.
,
.

IRC
, - IRC.
, , -
.
482 .

, , ,
.
, IRC
, (, https://bpaste.net/+python/).

.
.
.
, - .
-
.
.
Git

-
, .
(, )
,
, .
-
,
. ,
, .
, Git
, .
Git . -
Git ,
, -
-. Git ,
; ,
.

Git
Git ,
.
.

Git Linux
Git Linux, :
$ sudo apt-get install git

, Git .

Git OS X
, Git ;
git --version. , Git
484 . Git

.
Git, .
: https://git-scm.com/,
Downloads .

Git Windows
Git Windows http://msysgit.github.io/.

Git
Git , , -
. Git
. ,
:
$ git config --global user.name "_"
$ git config --global user.email "username@example.com"

, Git .


.
git_practice. Python:

hello_world.py
print("Hello Git world!")

Git.


.pyc .py, -
Git . __pycache__.
Git ,
.gitignore ( )
:
.gitignore
__pycache__/
Git ,
__pycache__. .gitignore
.
485

Python 2.7, *.pyc. Python 2.7


__pycache__; .pyc .py. -
(*) Git .pyc.
, .gitignore
, . -
, .


, Python .gitignore,
Git. ,
git_practice :
git_practice$ git init
Initialized empty Git repository in git_practice/.git/
git_practice$

, Git -
git_practice. ,
Git. , Git
, .git/,
. ,
.


-, :
git_practice$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# hello_world.py
#
nothing added to commit but untracked files present (use "git add" to track)
git_practice$

Git (branch) , ;
, master . ,
, ,
master. , -
. (commit)
.
486 . Git

Git , ,
Git, . ,
,
, .


:
git_practice$ git add .
git_practice$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: hello_world.py
#
git_practice$

git , -
. ; Git,
. ,
Git , . new file ,
.

:
git_practice$ git commit -m "Started project."
[master (root-commit) c03d2a3] Started project.
2 files changed, 1 insertion(+)
create mode 100644 .gitignore
create mode 100644 hello_world.py
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$

git commit -m "" -


. -m Git ("Started
project.") . ,
master , .
, master,
. , -
. ,
; , .
487


Git , .
:
git_practice$ git log
commit a9d74d87f1aa3b8f5b2688cb586eac1a908cfc7f
Author: Eric Matthes <eric@example.com>
Date: Mon Mar 16 07:23:32 2015 -0800

Started project.
git_practice$

, , Git -
40 . , -
, , .
, Git
:
git_practice$ git log --pretty=oneline
a9d74d87f1aa3b8f5b2688cb586eac1a908cfc7f Started project.
git_practice$

--pretty=oneline :
.


,
. hello_world.py:
hello_world.py
print("Hello Git world!")
print("Hello everyone.")

, , Git:
git_practice$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: hello_world.py
#
no changes added to commit (use "git add" and/or "git commit -a")
git_practice$

, ,
, .
:
488 . Git

git_practice$ git commit -am "Extended greeting."


[master 08d4d5e] Extended greeting.
1 file changed, 1 insertion(+)
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$ git log --pretty=oneline
08d4d5e39cb906f6cff197bd48e9ab32203d7ed6 Extended greeting.
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$

git commit -am . -a -


Git .
( ,
git add., .) -m -
Git .
. -
, .


, -
. hello_world.py :
hello_world.py
print("Hello Git world!")
print("Hello everyone.")

print("Oh no, I broke the project!")

.
, Git :
git_practice$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: hello_world.py
#
no changes added to commit (use "git add" and/or "git commit -a")
git_practice$

Git , hello_world.py ,
.
, -
. hello_world.py : ,
.
:
489

git_practice$ git checkout .


git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$

git checkout
. git checkout . ,
,
.
, , hello_world.py
:
print("Hello Git world!")
print("Hello everyone.")

-
,
, , ,
. :
,
, .
; Git .

, .


Git , .
6
. ,
,
:
git_practice$ git log --pretty=oneline
08d4d5e39cb906f6cff197bd48e9ab32203d7ed6 Extended greeting.
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$ git checkout be017b
Note: checking out 'be017b'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

HEAD is now at be017b7... Started project.


git_practice$
490 . Git

master
, Git HEAD . HEAD
; , -
(master ).
master, :
git_practice$ git checkout master
Previous HEAD position was be017b7... Started project.
Switched to branch 'master'
git_practice$

master. -
, -
Git. ,
. master ,
:
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$ git log --pretty=oneline
08d4d5e39cb906f6cff197bd48e9ab32203d7ed6 Extended greeting.
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$ git reset --hard be017b
HEAD is now at be017b7 Started project.
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$ git log --pretty=oneline
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$

,
master . .
git reset --hard ,
. ,
, .
, , -
.


, ,
. , ,
. ,
, ,
, .git. , -
,
.
491


.git, .
, .
:
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$ rm -rf .git
git_practice$ git status
fatal: Not a git repository (or any of the parent directories): .git
git_practice$ git init
Initialized empty Git repository in git_practice/.git/
git_practice$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# hello_world.py
#
nothing added to commit but untracked files present (use "git add" to track)
git_practice$ git add .
git_practice$ git commit -m "Starting over."
[master (root-commit) 05f5e01] Starting over.
2 files changed, 2 insertions(+)
create mode 100644 .gitignore
create mode 100644 hello_world.py
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$

, . -
rm -rf .git (rmdir /s .git Windows) .git .
.git -
Git. , Git ,
.git,
.
git init -
. , ,
. -
. ,
master, .
,
, .

! Python
. ,
-.
, -
.
, -
. ,
, ,
, .
. -
, , ,
. -
.
.
- . -
, , .
-,
.
;
.
,
.
, Python.
Python
. -
PyCon.
,
, Python.
Python,
. , , -
, .
Python , -
Python .
,
.
!
Python!

Python. ,
, -
.

.
.
.
.
.

, 192102, -, . (. ), . 3, , . 7.

034-2014,
58.11.12.000 , .

20.09.16. 70100/16. . . . . 39,990. 1000. 0000.