forked from mattharrison/Tiny-Python-3.6-Notebook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpython.html
1434 lines (1361 loc) · 58.8 KB
/
python.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tiny Python 3.6 Notebook</title>
<link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>
<body class="stackedit">
<div class="stackedit__left">
<div class="stackedit__toc">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#running-python">Running Python</a>
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#invoking-python">Invoking Python</a></li>
<li><a href="#repl">REPL</a></li>
</ul>
</li>
<li><a href="#the-zen-of-python">The Zen of Python</a></li>
<li><a href="#built-in-types">Built-in Types</a>
<ul>
<li><a href="#variables">Variables</a></li>
<li><a href="#numbers">Numbers</a></li>
<li><a href="#strings">Strings</a></li>
<li><a href="#lists">Lists</a></li>
<li><a href="#dictionaries">Dictionaries</a></li>
<li><a href="#tuples">Tuples</a></li>
<li><a href="#sets">Sets</a></li>
</ul>
</li>
<li><a href="#built-in-functions">Built in Functions</a></li>
<li><a href="#unicode">Unicode</a></li>
<li><a href="#string-formatting">String Formatting</a>
<ul>
<li><a href="#conversion-flags">Conversion Flags</a></li>
<li><a href="#format-specification">Format Specification</a></li>
<li><a href="#some-format-examples">Some format Examples</a></li>
</ul>
</li>
<li><a href="#files">Files</a>
<ul>
<li><a href="#writing-files">Writing Files</a></li>
<li><a href="#reading-files">Reading Files</a></li>
</ul>
</li>
<li><a href="#functions">Functions</a>
<ul>
<li><a href="#defining-functions">Defining functions</a></li>
<li><a href="#calling-functions">Calling Functions</a></li>
<li><a href="#getting-help">Getting Help</a></li>
</ul>
</li>
<li><a href="#classes">Classes</a>
<ul>
<li><a href="#subclasses">Subclasses</a></li>
<li><a href="#class-methods-and-static-methods">Class Methods and Static Methods</a></li>
<li><a href="#properties">Properties</a></li>
</ul>
</li>
<li><a href="#looping">Looping</a>
<ul>
<li><a href="#while-loops">while Loops</a></li>
<li><a href="#iteration-protocol">Iteration Protocol</a></li>
</ul>
</li>
<li><a href="#conditionals">Conditionals</a>
<ul>
<li><a href="#truthiness">Truthiness</a></li>
<li><a href="#short-circuiting">Short Circuiting</a></li>
<li><a href="#ternary-operator">Ternary Operator</a></li>
</ul>
</li>
<li><a href="#exceptions">Exceptions</a>
<ul>
<li><a href="#raising-exceptions">Raising Exceptions</a></li>
</ul>
</li>
<li><a href="#decorators">Decorators</a>
<ul>
<li><a href="#parameterized-decorators">Parameterized Decorators</a></li>
</ul>
</li>
<li><a href="#class-decorators-and-metaclasses">Class Decorators and Metaclasses</a>
<ul>
<li><a href="#class-decorators">Class Decorators</a></li>
<li><a href="#creating-classes-with-type">Creating Classes with type</a></li>
<li><a href="#metaclasses-with-functions">Metaclasses with Functions</a></li>
<li><a href="#metaclasses-with-classes">Metaclasses with Classes</a></li>
</ul>
</li>
<li><a href="#generators">Generators</a></li>
<li><a href="#coroutines">Coroutines</a>
<ul>
<li><a href="#asynchronous-generators">Asynchronous Generators</a></li>
</ul>
</li>
<li><a href="#comprehensions">Comprehensions</a>
<ul>
<li><a href="#set-comprehensions">Set Comprehensions</a></li>
<li><a href="#dict-comprehensions">Dict Comprehensions</a></li>
<li><a href="#generator-expressions">Generator Expressions</a></li>
<li><a href="#asynchronous-comprehensions">Asynchronous Comprehensions</a></li>
</ul>
</li>
<li><a href="#context-managers">Context Managers</a>
<ul>
<li><a href="#function-based-context-managers">Function Based Context Managers</a></li>
<li><a href="#class-based-context-managers">Class Based Context Managers</a></li>
<li><a href="#context-objects">Context objects</a></li>
</ul>
</li>
<li><a href="#type-annotations">Type Annotations</a>
<ul>
<li><a href="#the-typing-module">The typing Module</a></li>
<li><a href="#type-checking">Type Checking</a></li>
</ul>
</li>
<li><a href="#scripts-packages-and-modules">Scripts, Packages, and Modules</a>
<ul>
<li><a href="#scripts">Scripts</a></li>
<li><a href="#modules">Modules</a></li>
<li><a href="#packages">Packages</a></li>
<li><a href="#importing">Importing</a></li>
</ul>
</li>
<li><a href="#environments">Environments</a>
<ul>
<li><a href="#installing-packages">Installing Packages</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="stackedit__right">
<div class="stackedit__html">
<h1 id="introduction">Introduction</h1>
<p>This is not so much an instructional manual, but rather notes, tables, and examples for Python syntax. It was created by the author as an additional resource during training, meant to be distributed as a physical notebook. Participants (who favor the physical characteristics of dead tree material) could add their own notes, thoughts, and have a valuable reference of curated examples.</p>
<h1 id="running-python">Running Python</h1>
<h2 id="installation">Installation</h2>
<p>To check if Python is installed, run the following from a terminal:</p>
<pre><code>$ python3 --version
</code></pre>
<p>Otherwise, install Python 3 from the website <sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup>.</p>
<h2 id="invoking-python">Invoking Python</h2>
<p>The Python executable will behave differently depending on the command line options you give it:</p>
<ul>
<li>
<p>Start the Python REPL:</p>
<pre><code>$ python3
</code></pre>
</li>
<li>
<p>Execute the <code>file.py</code> file:</p>
<pre><code>$ python3 file.py
</code></pre>
</li>
<li>
<p>Execute the <code>file.py</code> file, and drop into REPL with namespace of <code>file.py</code>:</p>
<pre><code>$ python3 -i file.py
</code></pre>
</li>
<li>
<p>Execute the <code>json/tool.py</code> module:</p>
<pre><code>$ python3 -m json.tool
</code></pre>
</li>
<li>
<p>Execute <code>"print('hi')"</code> :</p>
<pre><code>$ python3 -c "print('hi')"
</code></pre>
</li>
</ul>
<h2 id="repl">REPL</h2>
<ul>
<li>Use the <code>help</code> function to read the documentation for a module/class/function. As a standalone invocation, you enter the help system and can explore various topics.</li>
<li>Use the <code>dir</code> function to list contents of the namespace, or attributes of an object if you pass one in.</li>
</ul>
<blockquote>
<p><strong>note</strong></p>
<p>The majority of code in this book is written as if it were executed in a REPL. If you are typing it in, ignore the primary and secondary prompts (<code>>>></code> and <code>...</code>).</p>
</blockquote>
<h1 id="the-zen-of-python">The Zen of Python</h1>
<p>Run the following in an interpreter to get an Easter egg that describes some of the ethos behind Python. This is also codified in PEP 20:</p>
<pre><code>>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the
rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation
to guess.
There should be one --and preferably only one--
obvious way to do it.
Although that way may not be obvious at first
unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a
bad idea.
If the implementation is easy to explain, it may
be a good idea.
Namespaces are one honking great idea -- let's
do more of those!
</code></pre>
<p>These might just seem like silly one liners, but there is a lot of wisdom packed in here. It is good for Python programmers to review these every once in a while and see if these hold true for their code. (Or to justify their code reviews)</p>
<h1 id="built-in-types">Built-in Types</h1>
<h2 id="variables">Variables</h2>
<p>Python variables are like cattle tags, they point to objects (which can be classes, instances, modules, or functions), but variables are not the objects. You can reuse variable names for different object types (though you probably shouldn’t):</p>
<pre><code>>>> a = 400 # a points to an integer
>>> a = '400' # a now points to a string
</code></pre>
<blockquote>
<p><strong>note</strong></p>
<p>The <code>#</code> character denotes the start of a comment. There are no multi-line comments, though most editors with Python support can comment out a region.</p>
</blockquote>
<p>The figure that follows illustrates how everything is an object in Python and variables just point to them.</p>
<p><img src="https://github.com/rkennesson/Tiny-Python-3.6-Notebook/blob/master/img/py/rebind.png?raw=true" alt="Illustration of reusing the same variable"></p>
<h2 id="numbers">Numbers</h2>
<p>Python includes three types of numeric literals: <em>integers</em>, <em>floats</em>, and <em>complex numbers</em>. Python 3.6 adds the ability to use underscores to improve readability (PEP 515).</p>
<p>There are many built-in functions for manipulating numbers ie. <code>abs</code>, <code>min</code>, <code>max</code>, <code>ceil</code>. Also see the <code>math</code>, <code>random</code>, and <code>statistics</code> modules in the standard library.</p>
<h2 id="strings">Strings</h2>
<p>Python 3 strings hold unicode data. Python has a few ways to represent strings. There is also a bytes type (PEP 3137):</p>
<h2 id="lists">Lists</h2>
<p>Lists are ordered mutable sequences:</p>
<pre><code>>>> people = ['Paul', 'John', 'George']
>>> people.append('Ringo')
</code></pre>
<p>The <code>in</code> operator is useful for checking membership on sequences:</p>
<pre><code>>>> 'Yoko' in people
False
</code></pre>
<p>If we need the index number during iteration, the <code>enumerate</code> function gives us a tuple of index, item pairs:</p>
<pre><code>>>> for i, name in enumerate(people, 1):
... print('{} - {}'.format(i, name))
1 - Paul
2 - John
3 - George
4 - Ringo
</code></pre>
<p>We can do index operations on most sequences:</p>
<pre><code>>>> people[0]
'Paul'
>>> people[-1] # len(people) - 1
'Ringo'
</code></pre>
<p>We can also do <em>slicing</em> operations on most sequences:</p>
<pre><code>>>> people[1:2]
['John']
>>> people[:1] # Implicit start at 0
['Paul']
>>> people[1:] # Implicit end at len(people)
['John', 'George', 'Ringo']
>>> people[::2] # Take every other item
['Paul', 'George']
>>> people[::-1] # Reverse sequence
['Ringo', 'George', 'John', 'Paul']
</code></pre>
<h2 id="dictionaries">Dictionaries</h2>
<p>Dictionaries are mutable mappings of keys to values. Keys must be hashable, but values can be any object:</p>
<pre><code>>>> instruments = {'Paul': 'Bass',
... 'John': 'Guitar'}
>>> instruments['George'] = 'Guitar'
>>> 'Ringo' in instruments
False
>>> for name in instruments:
... print('{} - {}'.format(name,
... instruments[name]))
Paul - Bass
John - Guitar
George - Guitar
</code></pre>
<h2 id="tuples">Tuples</h2>
<p>Tuples are immutable sequences. Typically they are used to store <em>record</em> type data:</p>
<pre><code>>>> member = ('Paul', 'Bass', 1942)
>>> member2 = ('Ringo', 'Drums', 1940)
</code></pre>
<p>Note that parentheses aren’t usually required:</p>
<pre><code>>>> row = 1, 'Fred' # 2 item tuple
>>> row2 = (2, 'Bob') # 2 item tuple
>>> row3 = ('Bill') # String!
>>> row4 = ('Bill',) # 1 item tuple
>>> row5 = 'Bill', # 1 item tuple
>>> row6 = () # Empty tuple
</code></pre>
<p>Named tuples can be used in place of normal tuples and allow context (or names) to be added to positional members. The syntax for creating them is a little different because we are dynamically creating a class first (hence the capitalized variable):</p>
<pre><code>>>> from collections import namedtuple
>>> Member = namedtuple('Member',
... 'name, instrument, birth_year')
>>> member3 = Member('George', 'Guitar', 1943)
</code></pre>
<p>We can access members by position or name (name allows us to be more explicit):</p>
<pre><code>>>> member3[0]
'George'
>>> member3.name
'George'
</code></pre>
<h2 id="sets">Sets</h2>
<p>A set is a mutable unordered collection that cannot contain duplicates. Sets are used to remove duplicates and test for membership:</p>
<pre><code>>>> digits = [0, 1, 1, 2, 3, 4, 5, 6,
... 7, 8, 9]
>>> digit_set = set(digits) # remove extra 1
>>> 9 in digit_set
True
</code></pre>
<p>Sets are useful because they provide <em>set operations</em>, such as union (<code>|</code>), intersection (<code>&</code>), difference (<code>-</code>), and xor (<code>^</code>):</p>
<pre><code>>>> odd = {1, 3, 5, 7, 9}
>>> prime = set([2, 3, 5, 7])
>>> even = digit_set - odd
>>> even
{0, 2, 4, 6, 8}
>>> prime & even # in intersection
{2}
>>> odd | even # in both
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> even ^ prime # not in both
{0, 3, 4, 5, 6, 7, 8}
</code></pre>
<blockquote>
<p><strong>note</strong></p>
<p>There is no literal syntax for an empty set. You need to use:</p>
<pre><code>>>> empty = set()
</code></pre>
</blockquote>
<h1 id="built-in-functions">Built in Functions</h1>
<p>In the default namespace you have access to various callables:</p>
<h1 id="unicode">Unicode</h1>
<p>Python 3 represents strings as Unicode. We can <em>encode</em> strings to a series of bytes such as UTF-8. If we have bytes, we can <em>decode</em> them to a Unicode string:</p>
<pre><code>>>> x_sq = 'x²'
>>> x_sq.encode('utf-8')
b'x\xc2\xb2'
>>> utf8_bytes = b'x\xc2\xb2'
>>> utf8_bytes.decode('utf-8')
'x²'
</code></pre>
<p>If you have the unicode glyph, you can use that directly. Alternatively, you can enter a code point using <code>\u</code> followed by the 16-bit hex value xxxx. For larger code points, use <code>\U</code> followed by xxxxxxxx. If you have the Unicode name (obtained by consulting tables at <a href="http://unicode.org">unicode.org</a>), you can use the <code>\N</code> syntax. The following are equivalent:</p>
<pre><code>>>> result = 'x²'
>>> result = 'x\u00b2'
>>> result = 'x\N{SUPERSCRIPT TWO}'
</code></pre>
<p><img src="https://github.com/rkennesson/Tiny-Python-3.6-Notebook/blob/master/img/py/uniencode.png?raw=true" alt="Image illustrating *encoding* a Unicode string to a byte representation. In this case, we convert to UTF-8. There are other byte encodings for this string. If we have a UTF-8 byte string, we can *decode* it into a Unicode string. Note that we should be explicit about the decoding as there are potentially other encodings that we could decode to that might give the user erroneous data, or *mojibake*."></p>
<h1 id="string-formatting">String Formatting</h1>
<p>Most modern Python code uses the <code>.format</code> method (PEP 3101) to create strings from other parts. The format method uses <code>{}</code> as a placeholder.</p>
<p>Inside of the placeholder we can provide different specifiers:</p>
<ul>
<li><code>{0}</code> - reference first positional argument</li>
<li><code>{}</code> - reference implicit positional argument</li>
<li><code>{result}</code> - reference keyword argument</li>
<li><code>{bike.tire}</code> - reference attribute of argument</li>
<li><code>{names[0]}</code> - reference first element of argument</li>
</ul>
<!-- -->
<pre><code>>>> person = {'name': 'Paul',
... 'instrument': 'Bass'}
>>> inst = person['instrument']
>>> print("Name: {} plays: {}".format(
... person['name'], inst))
Name: Paul plays: Bass
</code></pre>
<p>or:</p>
<pre><code>>>> print("Name: {name} "
... "plays: {inst}".format(
... name=person['name'], inst=inst))
Name: Paul plays: Bass
</code></pre>
<p>You can also use <em>f-strings</em> in Python 3.6 (see PEP 498):</p>
<pre><code>>>> print(f'Name: {person["name"]} plays: {inst}')
Name: Paul plays: Bass
</code></pre>
<p>F-strings inspect variables that are available and allow you to inline methods, or attributes from those variables.</p>
<h2 id="conversion-flags">Conversion Flags</h2>
<p>You can provide a <em>conversion flag</em> inside the placeholder.</p>
<ul>
<li><code>!s</code> - Call <code>str()</code> on argument</li>
<li><code>!r</code> - Call <code>repr()</code> on argument</li>
<li><code>!a</code> - Call <code>ascii()</code> on argument</li>
</ul>
<!-- -->
<pre><code>>>> class Cat:
... def __init__(self, name):
... self.name = name
... def __format__(self, data):
... return "Format"
... def __str__(self):
... return "Str"
... def __repr__(self):
... return "Repr"
>>> cat = Cat("Fred")
>>> print("{} {!s} {!a} {!r}".format(cat, cat, cat,
... cat))
Format Str Repr Repr
</code></pre>
<h2 id="format-specification">Format Specification</h2>
<p>You can provide a format specification following a colon. The grammar for format specification is as follows:</p>
<pre><code>[[fill]align][sign][#][0][width][grouping_option]
[.precision][type]
</code></pre>
<p>The following table lists the field meanings.</p>
<p>Field Meaning</p>
<hr>
<p>fill Fills in space with <code>align</code><br>
align <code><</code>-left align,<br>
<code>></code>-right align,<br>
<code>^</code>-center align,<br>
<code>=</code>-put padding after sign<br>
sign <code>+</code>-for all number,<br>
<code>-</code>-only negative,<br>
<em>space</em>-leading space for<br>
positive, sign on negative<br>
# Prefix integers. <code>Ob</code>-binary,<br>
<code>0o</code>-octal, <code>0x</code>-hex<br>
0 Enable zero padding<br>
width Minimum field width<br>
grouping_option <code>,</code>-Use comma for thousands<br>
separator, <code>_</code>-Use underscore<br>
for thousands separator<br>
.precision Digits after period (floats).<br>
Max string length (non-numerics)<br>
type <code>s</code>-string format (default)<br>
see Integer and Float charts</p>
<p>The tables below lists the various options we have for formatting integer and floating point numbers.</p>
<p>Integer Types Meaning</p>
<hr>
<p><code>b</code> binary<br>
<code>c</code> character - convert to unicode<br>
character<br>
<code>d</code> decimal (default)<br>
<code>n</code> decimal with locale specific<br>
separators<br>
<code>o</code> octal<br>
<code>x</code> hex (lower-case)<br>
<code>X</code> hex (upper-case)</p>
<p>Float Types Meaning</p>
<hr>
<p><code>e</code>/<code>E</code> Exponent. Lower/upper-case e<br>
<code>f</code> Fixed point<br>
<code>g</code>/<code>G</code> General. Fixed with exponent for<br>
large,<br>
and small numbers (<code>g</code> default)<br>
<code>n</code> <code>g</code> with locale specific<br>
separators<br>
<code>%</code> Percentage (multiplies by 100)</p>
<h2 id="some-format-examples">Some <code>format</code> Examples</h2>
<p>Here are a few examples of using <code>.format</code>. Let’s format a string in the center of 12 characters surrounded by <code>*</code>. <code>*</code> is the <em>fill</em> character, <code>^</code> is the <em>align</em> field, and <code>12</code> is the <em>width</em> field:</p>
<pre><code>>>> "Name: {:*^12}".format("Ringo")
'Name: ***Ringo****'
</code></pre>
<p>Next, we format a percentage using a width of 10, one decimal place and the sign before the width padding. <code>=</code> is the <em>align</em> field, <code>10.1</code> are the <em>width</em> and <em>precision</em> fields, and <code>%</code> is the <em>float type</em>, which converts the number to a percentage:</p>
<pre><code>>>> "Percent: {:=10.1%}".format(-44/100)
'Percent: - 44.0%'
</code></pre>
<p>Below is a binary and a hex conversion. The <em>integer type</em> field is set to <code>b</code> and <code>x</code> respectively:</p>
<pre><code>>>> "Binary: {:#b}".format(12)
'Binary: 0b1100'
>>> "Hex: {:#x}".format(12)
'Hex: 0xc'
</code></pre>
<h1 id="files">Files</h1>
<p>The <code>open</code> function will take a file path and mode as input and return a file handle. There are various modes to open a file, depending on the content and your needs. If you open the file in binary mode, you will get bytes out. In text mode you will get strings back:</p>
<h2 id="writing-files">Writing Files</h2>
<p>We use a context manager with a file to ensure that the file is closed when the context block exits.</p>
<pre><code>>>> with open('/tmp/names.txt', 'w') as fout:
... fout.write('Paul\r\nJohn\n')
... fout.writelines(['Ringo\n', 'George\n'])
</code></pre>
<h2 id="reading-files">Reading Files</h2>
<p>With an opened text file, you can iterate over the lines. This saves memory as the lines are read in as needed:</p>
<pre><code>>>> with open('/tmp/names.txt') as fin:
... for line in fin:
... print(repr(line))
'Paul\n'
'John\n'
'Ringo\n'
'George\n'
</code></pre>
<h1 id="functions">Functions</h1>
<h2 id="defining-functions">Defining functions</h2>
<p>Functions may take input, do some processing, and return output. You can provide a docstring directly following the name and parameters of the function:</p>
<pre><code>>>> def add_numbers(x, y):
... """ add_numbers sums up x and y
...
... Arguments:
... x -- object that supports addition
... y -- object that supports addition
... """
... return x + y
</code></pre>
<blockquote>
<p><strong>note</strong></p>
<p>We use whitespace to specify a block in Python. We typically indent following a colon. PEP 8 recommends using 4 spaces. Don’t mix tabs and spaces.</p>
</blockquote>
<p>We can create anonymous functions using the <code>lambda</code> statement. Because they only allow an expression following the colon, it is somewhat crippled in functionality. They are commonly used as a <code>key</code> argument to <code>sorted</code>, <code>min</code>, or <code>max</code>:</p>
<pre><code>>>> add = lambda x, y: x + y
>>> add(4, 5)
9
</code></pre>
<p>Functions can have <em>default</em> arguments. Be careful with mutable types here, as the default is bound to the function when the function is created, not when it is called:</p>
<pre><code>>>> def add_n(x, n=42):
... return x + n
>>> add_n(10)
52
>>> add_n(3, -10)
-7
</code></pre>
<p>Functions can support variable positional arguments:</p>
<pre><code>>>> def add_many(*args):
... result = 0
... for arg in args:
... result += arg
... return result
>>> add_many()
0
>>> add_many(1)
1
>>> add_many(42, 3.14)
45.14
</code></pre>
<p>Functions can support variable keyword arguments:</p>
<pre><code>>>> def add_kwargs(**kwargs):
... result = 0
... for key in kwargs:
... result += kwargs[key]
... return result
>>> add_kwargs(x=1, y=2, z=3)
6
>>> add_kwargs()
0
>>> add_kwargs(4)
Traceback (most recent call last):
...
TypeError: add_kwargs() takes 0 positional arguments
but 1 was given
</code></pre>
<p>You can indicate the end of positional parameters by using a single <code>*</code>. This gives you <em>keyword only</em> parameters (PEP 3102):</p>
<pre><code>>>> def add_points(*, x1=0, y1=0, x2=0, y2=0):
... return x1 + x2, y1 + y2
>>> add_points(x1=1, y1=1, x2=3, y2=4)
(4, 5)
>>> add_points(1, 1, 3, 4)
Traceback (most recent call last):
...
TypeError: add_points() takes 0 positional arguments
but 4 were given
</code></pre>
<h2 id="calling-functions">Calling Functions</h2>
<p>You can also use <code>*</code> and <code>**</code> to <em>unpack</em> sequence and dictionary arguments:</p>
<pre><code>>>> def add_all(*args, **kwargs):
... """Add all arguments"""
... result = 0
... for num in args + tuple(kwargs.values()):
... result += num
... return result
>>> sizes = (2, 4.5)
>>> named_sizes = {"this": 3, "that": 1}
</code></pre>
<p>The following two examples are the equivalent:</p>
<pre><code>>>> add_all(*sizes)
6.5
>>> add_all(sizes[0], sizes[1])
6.5
</code></pre>
<p>\Needspace{5\baselineskip}<br>
The following two examples are the equivalent:</p>
<pre><code>>>> add_all(**named_sizes)
4
>>> add_all(this=3, that=1)
4
</code></pre>
<p>You can also combine <code>*</code> and <code>**</code> on invocation:</p>
<pre><code>>>> add_all(*sizes, **named_sizes)
10.5
</code></pre>
<h2 id="getting-help">Getting Help</h2>
<p>You can get help on a function that has a docstring by using <code>help</code>:</p>
<pre><code>>>> help(add_all)
Help on function add_all in module __main__:
add_all(*args, **kwargs)
Add all arguments
</code></pre>
<h1 id="classes">Classes</h1>
<p>Python supports object oriented programming but doesn’t require you to create classes. You can use the built-in data structures to great effect. Here’s a class for a simple bike. The class attribute, <code>num_passengers</code>, is shared for all instances of <code>Bike</code>. The instance attributes, <code>size</code> and <code>ratio</code>, are unique to each instance:</p>
<pre><code>>>> class Bike:
... ''' Represents a bike '''
... num_passengers = 1 # class attribute
...
... def __init__(self, wheel_size,
... gear_ratio):
... ''' Create a bike specifying the
... wheel size, and gear ratio '''
... # instance attributes
... self.size = wheel_size
... self.ratio = gear_ratio
...
... def gear_inches(self):
... return self.ratio * self.size
</code></pre>
<p>We can call the constructor (<code>__init__</code>), by invoking the class name. Note that <code>self</code> is the instance, but Python passes that around for us automatically:</p>
<pre><code>>>> bike = Bike(26, 34/13)
>>> print(bike.gear_inches())
68.0
</code></pre>
<p>We can access both class attributes and instance attributes on the instance:</p>
<pre><code>>>> bike.num_passengers
1
>>> bike.size
26
</code></pre>
<p>If an attribute is not found on the instance, Python will then look for it on the class, it will look through the parent classes to continue to try and find it. If the lookup is unsuccessful, an <code>AttributeError</code> is raised.</p>
<h2 id="subclasses">Subclasses</h2>
<p>To subclass a class, simply place the parent class name in parentheses following the class name in the declaration. We can call the <code>super</code> function to gain access to parent methods:</p>
<pre><code>>>> class Tandem(Bike):
... num_passengers = 2
...
... def __init__(self, wheel_size, rings, cogs):
... self.rings = rings
... self.cogs = cogs
... ratio = rings[0] / cogs[0]
... super().__init__(wheel_size, ratio)
...
... def shift(self, ring_idx, cog_idx):
... self.ratio = self.rings[ring_idx] \
... / self.cogs[cog_idx]
...
</code></pre>
<blockquote>
<p><strong>note</strong></p>
<p>In the above example, we used a <code>\</code> to indicate that the line continued on the following line. This is usually required unless there is an implicit line continuation with an opening brace that hasn’t been closed (<code>(</code>, <code>[</code>, or <code>{</code>).</p>
</blockquote>
<p>The instance of the subclass can call methods that are defined on its class or the parent class:</p>
<pre><code>>>> tan = Tandem(26, [42, 36], [24, 20, 15, 11])
>>> tan.shift(1, -1)
>>> tan.gear_inches()
85.0909090909091
</code></pre>
<h2 id="class-methods-and-static-methods">Class Methods and Static Methods</h2>
<p>The <code>classmethod</code> decorator is used to create methods that you can invoke directly on the class. This allows us to create alternate constructors. Note that the implicit first argument is the class, commonly named <code>cls</code> (as <code>class</code> is a keyword and will error out):</p>
<pre><code>>>> INCHES_PER_METER = 39.37
>>> class MountainBike(Bike):
... @classmethod
... def from_metric(cls, size_meters, ratio):
... return cls(size_meters *
... INCHES_PER_METER,
... ratio)
>>> mtn = MountainBike.from_metric(.559, 38/11)
>>> mtn.gear_inches()
76.0270490909091
</code></pre>
<blockquote>
<p><strong>note</strong></p>
<p>In the above example, we had an implicit line continuation without a backslash, because there was a <code>(</code> on the line.</p>
</blockquote>
<p>The <code>staticmethod</code> decorator lets you attach functions to a class. (I don’t like them, just use a function). Note that they don’t get an implicit first argument. It can be called on the instance or the class:</p>
<pre><code>>>> class Recumbent(Bike):
... @staticmethod
... def is_fast():
... return True
>>> Recumbent.is_fast()
True
>>> lawnchair = Recumbent(20, 4)
>>> lawnchair.is_fast()
True
</code></pre>
<h2 id="properties">Properties</h2>
<p>If you want to have actions occur under the covers on attribute access, you can use properties to do that:</p>
<pre><code>>>> class Person:
... def __init__(self, name):
... self._name = name
...
... @property
... def name(self):
... if self._name == 'Richard':
... return 'Ringo'
... return self._name
...
... @name.setter
... def name(self, value):
... self._name = value
...
... @name.deleter
... def name(self):
... del self._name
</code></pre>
<p>Rather than calling the <code>.name()</code> method, we access the attribute:</p>
<pre><code>>>> p = Person('Richard')
>>> p.name
'Ringo'
>>> p.name = 'Fred'
</code></pre>
<h1 id="looping">Looping</h1>
<p>You can loop over objects in a sequence:</p>
<pre><code>>>> names = ['John', 'Paul', 'Ringo']
>>> for name in names:
... print(name)
John
Paul
Ringo
</code></pre>
<p>The <code>break</code> statement will pop you out of a loop:</p>
<pre><code>>>> for name in names:
... if name == 'Paul':
... break
... print(name)
John
</code></pre>
<p>The <code>continue</code> statement skips over the body of the loop and <em>continues</em> at the next item of iteration:</p>
<pre><code>>>> for name in names:
... if name == 'Paul':
... continue
... print(name)
John
Ringo
</code></pre>
<p>You can use the <code>else</code> statement to indicate that every item was looped over, and a <code>break</code> was never encountered:</p>
<pre><code>>>> for name in names:
... if name == 'George':
... break
... else:
... raise ValueError("No Georges")
Traceback (most recent call last):
...
ValueError: No Georges
</code></pre>
<p>Don’t loop over index values (<code>range(len(names))</code>). Use <code>enumerate</code>:</p>
<pre><code>>>> for i, name in enumerate(names, 1):
... print("{}. {}".format(i, name))
1. John
2. Paul
3. Ringo
</code></pre>
<h2 id="while-loops"><code>while</code> Loops</h2>
<p>You can use <code>while</code> loops to create loops as well. If it is an infinite loop, you can break out of it:</p>
<pre><code>>>> done = False
>>> while not done:
... # some work
... done = True
</code></pre>
<h2 id="iteration-protocol">Iteration Protocol</h2>
<p>To make an iterator implement <code>__iter__</code> and <code>__next__</code>:</p>
<pre><code>>>> class fib:
... def __init__(self, limit=None):
... self.val1 = 1
... self.val2 = 1
... self.limit = limit
...
... def __iter__(self):
... return self
...
... def __next__(self):
... val = self.val1
... self.val1 = self.val2
... self.val2 = val + self.val1
... if self.limit is not None and \
... val < self.limit:
... return val
... raise StopIteration
</code></pre>
<p>Use the iterator in a loop:</p>
<pre><code>>>> e = fib(6)
>>> for val in e:
... print(val)
1
1
2
3
5
</code></pre>
<p>Unrolling the protocol:</p>
<pre><code>>>> e = fib(6)
>>> it = iter(e) # calls e.__iter__()
>>> next(it) # calls it.__next__()
1
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
5
>>> next(it)
Traceback (most recent call last):
...
StopIteration
</code></pre>
<h1 id="conditionals">Conditionals</h1>
<p>Python has an <code>if</code> statement with zero or more <code>elif</code> statements, and an optional <code>else</code> statement at the end. In Python, the word <code>elif</code> is Dutch for <em>else if</em>:</p>
<pre><code>>>> grade = 72
>>> def letter_grade(grade):
... if grade > 90:
... return 'A'
... elif grade > 80:
... return 'B'
... elif grade > 70:
... return 'C'
... else:
... return 'D'
>>> letter_grade(grade)
'C'
</code></pre>
<p>Python supports the following tests: <code>></code>, <code>>=</code>, <code><</code>, <code><=</code>, <code>==</code>, and <code>!=</code>. For boolean operators use <code>and</code>, <code>or</code>, and <code>not</code> (<code>&</code>, <code>|</code>, and <code>^</code> are the bitwise operators).</p>
<p>Note that Python also supports <em>range comparisons</em>:</p>
<pre><code>>>> x = 4
>>> if 3 < x < 5:
... print("Four!")
Four!
</code></pre>
<p>Python does not have a switch statement, often dictionaries are used to support a similar construct:</p>
<pre><code>>>> def add(x, y):
... return x + y
>>> def sub(x, y):
... return x - y
>>> ops = {'+': add, '-': sub}
>>> op = '+'
>>> a = 2
>>> b = 3
>>> ops[op](a, b)
5
</code></pre>
<h2 id="truthiness">Truthiness</h2>
<p>You can define the <code>__bool__</code> method to teach your classes how to act in a boolean context. If that doesn’t exists, Python will use <code>__len__</code>, and finally default to <code>True</code>.</p>
<p>The following table lists <em>truthy</em> and <em>falsey</em> values:</p>
<p>Truthy Falsey</p>
<hr>
<p><code>True</code> <code>False</code><br>
Most objects <code>None</code><br>
<code>1</code> <code>0</code><br>
<code>3.2</code> <code>0.0</code><br>
<code>[1, 2]</code> <code>[]</code> (empty list)<br>
<code>{'a': 1, 'b': 2}</code> <code>{}</code> (empty dict)<br>
<code>'string'</code> <code>""</code> (empty string)<br>
<code>'False'</code><br>
<code>'0'</code></p>
<h2 id="short-circuiting">Short Circuiting</h2>
<p>The <code>and</code> statement will short circuit if it evaluates to false:</p>
<pre><code>>>> 0 and 1/0
0
</code></pre>
<p>Likewise, the <code>or</code> statement will short circuit when something evaluates to true:</p>
<pre><code>>>> 1 or 1/0
1
</code></pre>
<h2 id="ternary-operator">Ternary Operator</h2>
<p>Python has its own ternary operator, called a <em>conditional expression</em> (see PEP 308). These are handy as they can be used in comprehension constructs and <code>lambda</code> functions:</p>
<pre><code>>>> last = 'Lennon' if band == 'Beatles' else 'Jones'
</code></pre>
<p>Note that this has similar behavior to an <code>if</code> statement, but it is an expression, and not a statement. Python distinguishes these two. An easy way to determine between the two, is to remember that an expression follows a <code>return</code> statement. Anything you can <code>return</code> is an expression.</p>
<h1 id="exceptions">Exceptions</h1>
<p>Python can catch one or more exceptions (PEP 3110). You can provide a chain of different exceptions to catch if you want to react differently. A few hints:</p>
<ul>
<li>Try to keep the block of the <code>try</code> statement down to the code that throws exceptions</li>
<li>Be specific about the exceptions that you catch</li>
<li>If you want to inspect the exception, use <code>as</code> to create a variable to point to it</li>
</ul>
<p>If you use a bare <code>raise</code> inside of an <code>except</code> block, Python’s traceback will point back to the location of the original exception, rather than where it is raised from.</p>
<pre><code>>>> def avg(seq):
... try:
... result = sum(seq) / len(seq)
... except ZeroDivisionError as e:
... return None
... except Exception:
... raise
... return result
>>> avg([1, 2, 4])
2.3333333333333335
>>> avg([]) is None
True
>>> avg('matt')
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'int'
and 'str'
</code></pre>
<h2 id="raising-exceptions">Raising Exceptions</h2>
<p>You can raise an exception using the <code>raise</code> statement (PEP 3109):</p>
<pre><code>>>> def bad_code(x):
... raise ValueError('Bad code')
>>> bad_code(1)
Traceback (most recent call last):
...
ValueError: Bad code
</code></pre>
<h1 id="decorators">Decorators</h1>
<p>A decorator (PEP 318) allows us to insert logic before and after a function is called. You can define a decorator with a function that takes a function as input and returns a function as output. Here is the identity decorator:</p>
<pre><code>>>> def identity(func):
... return func
</code></pre>
<p>We can decorate a function with it like this:</p>
<pre><code>>>> @identity
... def add(x, y):
... return x + y
</code></pre>
<p>A more useful decorator can inject logic before and after calling the original function. To do this we create a function inside of the function and return that:</p>
<pre><code>>>> import functools
>>> def verbose(func):
... @functools.wraps(func)
... def inner(*args, **kwargs):
... print("Calling with:{} {}".format(args,
... kwargs))
... res = func(*args, **kwargs)
... print("Result:{}".format(res))
... return res
... return inner
</code></pre>
<p>Above, we use print functions to illustrate before/after behavior, otherwise this is very similar to identity decorator.</p>
<p>There is a special syntax for applying the decorator. We put <code>@</code> before the decorator name and place that on a line directly above the function we wish to decorate. Using the <code>@verbose</code> line before a function declaration is syntactic sugar for re-assigning the variable pointing to the function to the result of calling the decorator with the function passed into it:</p>
<pre><code>>>> @verbose
... def sub(x, y):
... return x - y
</code></pre>
<p>This could also be written as, <code>sub = verbose(sub)</code>. Note that our decorated function will still call our original function, but add in some <code>print</code> statements:</p>
<pre><code>>>> sub(5, 4)
Calling with:(5, 4) {}
Result:1
1
</code></pre>
<h2 id="parameterized-decorators">Parameterized Decorators</h2>
<p>Because we can use closures to create functions, we can use closures to create decorators as well. This is very similar to our decorator above, but now we make a function that will return a decorator. Based on the inputs to that function, we can control (or parameterize) the behavior of the decorator:</p>
<pre><code>>>> def verbose_level(level):
... def verbose(func):
... @functools.wraps(func)
... def inner(*args, **kwargs):
... for i in range(level): # parameterized!
... print("Calling with:{} {}".format(
... args, kwargs))
... res = func(*args, **kwargs)
... print("Result:{}".format(res))
... return res
... return inner
... return verbose
</code></pre>
<p>When you decorate with parameterized decorators, the decoration looks differently, because we need to invoke the function to create a decorator:</p>
<pre><code>>>> @verbose_level(2)
... def div(x, y):
... return x/y
>>> div(1, 5)
Calling with:(1, 5) {}
Calling with:(1, 5) {}
Result:0.2
0.2
</code></pre>
<h1 id="class-decorators-and-metaclasses">Class Decorators and Metaclasses</h1>
<p>Python allows you to dynamically create and modify classes. Class decorators and metaclasses are two ways to do this.</p>
<h2 id="class-decorators">Class Decorators</h2>
<p>You can decorate a class definition with a <em>class decorator</em> (PEP 3129). It is a function that takes a class as input and returns a class.</p>
<pre><code>>>> def add_chirp(cls):