-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy path4_style.html
More file actions
1327 lines (1290 loc) · 99.1 KB
/
4_style.html
File metadata and controls
1327 lines (1290 loc) · 99.1 KB
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 lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>4. A matter of style — Object-oriented Programming documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="_static/fenics.css?v=8c7d05f9" />
<link rel="stylesheet" type="text/css" href="_static/proof.css" />
<link rel="stylesheet" type="text/css" href="_static/graphviz.css?v=fd3f3429" />
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/proof.js"></script>
<script async="async" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="5. Abstract data types" href="5_abstract_data_types.html" />
<link rel="prev" title="3. Objects and abstraction" href="3_objects.html" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="_static/ie6.css" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-0EFVH5C4DC"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-0EFVH5C4DC');
</script>
<link rel="stylesheet" href="_static/featured.css">
<link rel="shortcut icon" href="_static/icon.ico" />
</head><body>
<div class="wrapper">
<a href="index.html"><img src="_static/banner.png" width="900px" alt="FInAT Project Banner" /></a>
<div id="access">
<div class="menu">
<ul>
<li class="page_item"><a href="index.html" title="Book">Book</a></li>
<li class="page_item"><a href="videos.html" title="Videos">Videos</a></li>
<li class="page_item"><a href="exercises.html"
title="Exercises">Exercises</a></li>
<li class="page_item"><a href="installation.html" title="Installation">Installation</a></li>
</ul>
</div><!-- .menu -->
</div><!-- #access -->
</div><!-- #wrapper -->
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="a-matter-of-style">
<span id="style"></span><h1><span class="section-number">4. </span>A matter of style<a class="headerlink" href="#a-matter-of-style" title="Link to this heading">¶</a></h1>
<details>
<summary>
Video: why style?</summary><div class="video_wrapper" style="">
<iframe allowfullscreen="true" src="https://player.vimeo.com/video/499766703" style="border: 0; height: 345px; width: 560px">
</iframe></div><p>Imperial students can also <a class="reference external" href="https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=81bda525-60bb-46a7-bdc9-ae1c00da8a74">watch this video on Panopto</a></p>
</details><section id="the-value-of-convention">
<h2><span class="section-number">4.1. </span>The value of convention<a class="headerlink" href="#the-value-of-convention" title="Link to this heading">¶</a></h2>
<p>Consider the following definition of the limit of a function <span class="math notranslate nohighlight">\(f\)</span> at a
point <span class="math notranslate nohighlight">\(c\)</span>:</p>
<div class="proof proof-type-definition" id="id4">
<div class="proof-title">
<span class="proof-type">Definition 4.1</span>
</div><div class="proof-content">
<p>Suppose we have a function <span class="math notranslate nohighlight">\(f(x): \mathbb{R} \rightarrow \mathbb{R}\)</span>.
Then:</p>
<div class="math notranslate nohighlight">
\[\lim_{x\rightarrow c} f(x) = L \iff \forall\, \delta > 0,\ \exists\,
\epsilon > 0,\ |x - c| < \epsilon \Rightarrow |f(x) - L| < \delta\]</div>
</div></div><p>This is a perfectly valid definition of a limit: you could use it to go on and
derive all of real analysis. However, you would confuse yourself and your
readers horribly, because I have swapped the roles of <span class="math notranslate nohighlight">\(\delta\)</span> and
<span class="math notranslate nohighlight">\(\epsilon\)</span> in the definition. The formal properties of mathematical
objects do not depend on the names we give them or, often, on how we lay out
formulae on a page. However, mathematics is designed to be read by humans with
their habit-forming, pattern-matching brains. So if everyone adopts similar
conventions for how to write down mathematics, everyone schooled in those
conventions will find that mathematics easier to understand. This is vitally
important because understanding mathematics is hard. Non-standard notation
makes it doubly hard because the reader has to consciously remember the meaning
of all the symbols. Conversely, once a reader has learned the notational
conventions for a field of mathematics, the meanings of the symbols become
natural and don’t require conscious thought. This leaves all the available
brainpower to concentrate on the mathematical content at hand.</p>
<p>You might at first think that this logic does not apply to computer programs.
After all, a computer program is read by another computer program, and is not
understood but rather acted on mechanically. Surely it doesn’t matter how it
looks or what symbols you use, so long as it’s correct and, possibly, fast?
This entirely understandable sentiment has afflicted almost all programmers at
some point or another and typically has got them into more or less serious
difficulty before they realised that it’s completely wrong.</p>
<p>In reality, a computer program is frequently read. Indeed, code is typically
read many more times than it is written or changed. Most obviously, programmers
read code in order to understand its functionality, and in order to work out
what is wrong with the code when it fails to produce the correct results.
Reading code is very much like reading mathematics because a computer program
is nothing but a realisation of mathematical algorithms. Consequently, the
observation that maths can be very hard to read carries over to code. It is
therefore essential to make code as easy to understand as possible. Another
analogy that carries over from mathematics is that very often it’s one’s own
work that one is trying to understand and correct. This ought to create a very
strong incentive to write very clear code adhering to all the conventions,
because the poor individual who has to read your work to find the bugs might
very well be you!</p>
<p>Just as in mathematics, programming has a whole set of conventions which sit on
top of the formal requirements of a programming language. These exist in order
to make the code easier for all programmers to read. Some of these rules,
typically the more formulaic ones about matters such as code layout and naming
conventions, are somewhat different in different programming languages. Others,
most especially higher level principles like <a class="reference internal" href="#term-parsimony"><span class="xref std std-term">parsimony</span></a> and
<a class="reference internal" href="#term-modularity"><span class="xref std std-term">modularity</span></a>, are universal principles that apply more or less regardless
of the language employed or the sort of programming being undertaken. Good
programming style, like good writing style, is a skill learned through
experience and through receiving feedback on the code you write, and it is not
the intention of this chapter to produce an exhaustive guide. However, it is
useful to introduce some of the key concepts, rules and conventions in a more
formal way.</p>
</section>
<section id="pep-8">
<h2><span class="section-number">4.2. </span>PEP 8<a class="headerlink" href="#pep-8" title="Link to this heading">¶</a></h2>
<p>Publishers, journals, and institutions often have style guides
designed to instil a certain uniformity in the use of English (or
other human languages). Similarly, style guides exist for programming
languages. In some languages, the preferred style can vary
significantly from project to project, and there can be vigorous
disagreement between factions about fine points of style, such as
whether or not an opening curly bracket should start on a new
line. Fortunately, the Python community has an essentially unified and
very widely followed set of conventions. These are codified in one of
the Python standards documents, <a class="reference external" href="https://www.python.org/dev/peps/pep-0008/">PEP 8</a> <a class="footnote-reference brackets" href="#pep" id="id2" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>. PEP 8 isn’t all
that long, and it is worth taking the time to read. Not every rule in
PEP 8 is reproduced in this chapter, though many of the most commonly
encountered ones are. Conversely, PEP 8 is rather narrowly concerned
with code layout rules while this chapter roams more widely.</p>
<section id="linters">
<h3><span class="section-number">4.2.1. </span>Linters<a class="headerlink" href="#linters" title="Link to this heading">¶</a></h3>
<details>
<summary>
Video: installing and using a linter.</summary><div class="video_wrapper" style="">
<iframe allowfullscreen="true" src="https://player.vimeo.com/video/499770130" style="border: 0; height: 345px; width: 560px">
</iframe></div><p>Imperial students can also <a class="reference external" href="https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=63c09ddd-ec18-4746-b1b9-ae1c00da9680">watch this video on Panopto</a></p>
</details><p>One of the helpful characteristics of PEP 8 is that many of its strictures can
be enforced automatically by a computer program. Programs that automatically
check programming style are called linters. Lint are the little fibres that tend
to stick to clothes, especially suit jackets, and make them ugly. So a linter is
a program that finds the little ugly things in your code.</p>
<p>Originally, you ran the linter with your source file as an input, and it produced
a report as an output, listing all of the problems it found in your code. You
can still run a linter like this, and it’s very useful as an automated check
that the code committed to git is clean. However, Python-aware editors are often
able to run a linter for you, and display the results by highlighting code or
lines of code with problem. The effect is very like the highlighting of spelling
and grammar problems in many word processors and email clients.</p>
<p>One such program is called Flake8. Running Flake8 on all of the source
code in a project, preferably automatically on every commit, is an
excellent mechanism for keeping a project’s code in PEP 8
conformance. Indeed, without a mechanism like this, there is a strong
tendency for programmers to cut style corners, with the effect that
the code in a project becomes harder and harder to read and work with.</p>
</section>
<section id="installing-flake8">
<span id="flake8-extension"></span><h3><span class="section-number">4.2.2. </span>Installing Flake8<a class="headerlink" href="#installing-flake8" title="Link to this heading">¶</a></h3>
<p>Flake8 is a Python package, which can be installed using pip. Make sure you’ve
activated your <a class="reference internal" href="1_introduction.html#term-virtual-environment"><span class="xref std std-term">virtual environment</span></a> and then run:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp gp-VirtualEnv">(PoP_venv)</span> <span class="gp">$ </span>python<span class="w"> </span>-m<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>flake8
</pre></div>
</div>
<p>This is enough to run Flake8 on the command line, however you will probably want
to set up your editor to highlight PEP 8 incompatibilities in your source. For
Visual Studio Code:</p>
<ol class="arabic simple">
<li><dl class="simple">
<dt>Install the Flake8 extension:</dt><dd><ol class="loweralpha simple">
<li><p>Click the <img alt="extensions" src="_images/vscode_extensions.pdf" /> icon on the left of the screen.</p></li>
<li><p>Type <code class="xref py py-obj docutils literal notranslate"><span class="pre">Flake8</span></code> in the search box.</p></li>
<li><p>Click the blue <code class="xref py py-obj docutils literal notranslate"><span class="pre">Install</span></code> button.</p></li>
</ol>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt>Instruct the extension to use Flake8 from your virtual environment:</dt><dd><ol class="loweralpha simple">
<li><p>Type <kbd class="kbd docutils literal notranslate">control</kbd> + <kbd class="kbd docutils literal notranslate">,</kbd> (<kbd class="kbd docutils literal notranslate">⌘</kbd> + <kbd class="kbd docutils literal notranslate">,</kbd> on Mac) to open the <code class="xref py py-obj docutils literal notranslate"><span class="pre">Settings</span></code> tab.</p></li>
<li><p>Type <code class="xref py py-obj docutils literal notranslate"><span class="pre">flake8.importStrategy</span></code> in the <code class="xref py py-obj docutils literal notranslate"><span class="pre">Search</span> <span class="pre">settings</span></code> bar at the top of
the page.</p></li>
<li><p>Change the dropdown from <code class="xref py py-obj docutils literal notranslate"><span class="pre">useBundled</span></code> to <code class="xref py py-obj docutils literal notranslate"><span class="pre">fromEnvironment</span></code>.</p></li>
</ol>
</dd>
</dl>
</li>
</ol>
<p>The video for this section shows this process.</p>
</section>
<section id="how-to-tell-flake8-to-shut-up">
<h3><span class="section-number">4.2.3. </span>How to tell Flake8 to shut up<a class="headerlink" href="#how-to-tell-flake8-to-shut-up" title="Link to this heading">¶</a></h3>
<p>Near the top of PEP 8 is the following heading:</p>
<blockquote>
<div><p>A foolish consistency is the hobgoblin of little minds.</p>
</div></blockquote>
<p>What this refers to is that just religiously following PEP 8 is not enough to
produce highly readable code. Indeed, sometimes the rules might induce you do
to something which makes no sense at all. In those cases, one should step
outside PEP 8. This is a dangerous licence to take, and it is important to
point out that this does not mean that a programmer should ignore PEP 8 merely
because they disagree with a particular convention. Breaking PEP 8 is something
you should do only when you really have to.</p>
<p>In the rare cases where it is necessary to break PEP 8, Flake8 turns into a
problem. It doesn’t know anything of the judgement call that the programmer has
made, and so will complain about the offending code. For example, we have
learned that it is frequently desirable to import names in the
<code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file of a <a class="reference internal" href="2_programs_in_files.html#term-package"><span class="xref std std-term">package</span></a> in order to include them in the
package’s top level <a class="reference internal" href="2_programs_in_files.html#term-namespace"><span class="xref std std-term">namespace</span></a>. The problem with this is that these
names are not used inside the <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file so Flake8 will complain
that this is an unnecessary import.</p>
<p>One way to suppress linter errors is using a special comment at the end of the
line which causes the error. For example, <code class="file docutils literal notranslate"><span class="pre">fibonacci/__init__.py</span></code>
contains the following line:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">.fibonacci</span><span class="w"> </span><span class="kn">import</span> <span class="n">fib</span>
</pre></div>
</div>
<p>This causes the following Flake8 error:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>flake8<span class="w"> </span>fibonacci
<span class="go">fibonacci/__init__.py:1:1: F401 '.fibonacci.fib' imported but unused</span>
</pre></div>
</div>
<p>We suppress this error by adding this comment:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">.fibonacci</span><span class="w"> </span><span class="kn">import</span> <span class="n">fib</span> <span class="c1"># noqa F401</span>
</pre></div>
</div>
<p>The comment starts with the keyword <code class="xref py py-obj docutils literal notranslate"><span class="pre">noqa</span></code>, which stands for “no questions
asked” and then gives the error code which is to be ignored for this line. This
can be found in the Flake8 output.</p>
</section>
<section id="configuring-flake8">
<h3><span class="section-number">4.2.4. </span>Configuring Flake8<a class="headerlink" href="#configuring-flake8" title="Link to this heading">¶</a></h3>
<p><code class="xref py py-obj docutils literal notranslate"><span class="pre">noqa</span></code> comments are very useful for one-off suppression of Flake8
errors. However, it’s also likely to be the case that there are some rules that
you just don’t want to apply across your whole project. This configuration can
be achieved in the file <code class="file docutils literal notranslate"><span class="pre">setup.cfg</span></code>, which lives in the top of your
Git repository alongside <code class="file docutils literal notranslate"><span class="pre">pyproject.toml</span></code>. <code class="file docutils literal notranslate"><span class="pre">setup.cfg</span></code> can be
used to configure a lot of different Python tools, so it stores different
configurations in different sections. <a class="reference internal" href="#flake8conf"><span class="std std-numref">Listing 4.1</span></a> shows an example
Flake8 section. The full list of available options is presented in the <a class="reference external" href="https://flake8.pycqa.org">Flake8
documentation</a>.</p>
<div class="literal-block-wrapper docutils container" id="id5">
<span id="flake8conf"></span><div class="code-block-caption"><span class="caption-number">Listing 4.1 </span><span class="caption-text">A <code class="file docutils literal notranslate"><span class="pre">setup.cfg</span></code> Flake8 section which instructs Flake8 to
ignore the <code class="file docutils literal notranslate"><span class="pre">doc/</span></code> directory, to ignore rule <code class="xref py py-obj docutils literal notranslate"><span class="pre">D105</span></code> (docstrings
for magic methods), and to add in the non-default rule <code class="xref py py-obj docutils literal notranslate"><span class="pre">W504</span></code> (error
for a trailing operator at the end of a continued line).</span><a class="headerlink" href="#id5" title="Link to this code">¶</a></div>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[flake8]</span>
<span class="na">exclude</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">doc</span>
<span class="na">extend-ignore</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">D105</span>
<span class="na">extend-select</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">W504</span>
</pre></div>
</div>
</div>
</section>
</section>
<section id="code-layout">
<h2><span class="section-number">4.3. </span>Code layout<a class="headerlink" href="#code-layout" title="Link to this heading">¶</a></h2>
<p>Perhaps surprisingly, one of the most important factors in making code
readable is the space, or lack of it, between and around the text
which makes up the code. Whitespace affects readability in many
ways. Too much code bunched together makes it hard for the eye to
separate programme statements, while leaving too much space limits the
amount of code which fits in the editor window at once. This requires
the programmer to scroll constantly and to have to remember
definitions which are not currently on the screen.</p>
<p>As in written prose, whitespace can also convey information by
grouping together concepts which are related and separating distinct
ideas. This gives the reader visual clues which can aid in
understanding the code. With this in mind, we now turn to some of the
PEP 8 rules around white space and code formatting.</p>
<section id="blank-lines">
<h3><span class="section-number">4.3.1. </span>Blank lines<a class="headerlink" href="#blank-lines" title="Link to this heading">¶</a></h3>
<ol class="arabic simple">
<li><p>Classes and functions defined at the top level of a module
(i.e. not nested in other classes or functions) have two blank
lines before and after them. These are the largest and most
distinct units in a module, so it helps the reader to make them
quite distinct from each other.</p></li>
<li><p>Methods within a class are separated by a single blank
line. Similarly, functions defined inside other functions are
separated from surrounding code by a single blank line.</p></li>
<li><p>Statements within functions usually follow on the immediate next
line, except that logical groups of statements, can be separated by
single blank lines. Think of each statement as a sentence following
on from the previous, with blank lines used to divide the function
into short paragraphs.</p></li>
</ol>
<p><strong>Do not add extra blank lines to space out code</strong>. Vertical space on
the screen is limited, your readers will not thank you.</p>
</section>
<section id="white-space-within-lines">
<h3><span class="section-number">4.3.2. </span>White space within lines<a class="headerlink" href="#white-space-within-lines" title="Link to this heading">¶</a></h3>
<ol class="arabic">
<li><p>Don’t put a space after an opening bracket (of any shape), or
before a closing bracket. This is because the role of brackets is
to group their contents, so it’s confusing to visually separate the
bracket from the contents.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">(</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1"># Space after opening bracket.</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="p">)</span> <span class="c1"># Space before closing bracket.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1"># No space between brackets and contents.</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p>Similarly, don’t put a space between the function name and the
opening round bracket of a function call, or between a variable
name and the opening square bracket of an index. In each of these
cases, the opening bracket belongs to the object, so it’s confusing
to insert space between the object name and the bracket.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">sin</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># Space between function name and bracket.</span>
<span class="n">x</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># Space before index square bracket.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">sin</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p>Put a space after a comma but not before it, exactly like you would
in writing prose. Following the convention that everyone is used to
from writing aids understanding. Where a trailing comma comes right
before a closing bracket, then don’t put a space. The rule that
there are no spaces before a closing bracket is more important.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># Spaces missing after commas.</span>
<span class="p">(</span><span class="mi">1</span> <span class="p">,</span><span class="mi">2</span> <span class="p">,</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># Spurious spaces before commas.</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">)</span> <span class="c1"># Space before closing bracket.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1"># Spaces after commas.</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,)</span> <span class="c1"># No space before closing bracket.</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p>Put exactly one space on each side of an <a class="reference external" href="https://docs.python.org/3/reference/simple_stmts.html#assignment" title="(in Python v3.14)"><span class="xref std std-ref">assignment</span></a> (<code class="xref py py-obj docutils literal notranslate"><span class="pre">=</span></code>) and an
<a class="reference external" href="https://docs.python.org/3/reference/simple_stmts.html#augassign" title="(in Python v3.14)"><span class="xref std std-ref">augmented assignment</span></a> (<code class="xref py py-obj docutils literal notranslate"><span class="pre">+=</span></code>, <code class="xref py py-obj docutils literal notranslate"><span class="pre">-=</span></code>, etc.). In an assignment
statement, the most important distinction is between the left and
right hand sides of the assignment, so adding space here aids the
reader.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span><span class="o">=</span><span class="mi">1</span> <span class="c1"># Missing spaces around equals sign.</span>
<span class="n">x</span><span class="o">+=</span><span class="mi">1</span> <span class="c1"># Missing spaces around augmented addition operator.</span>
<span class="n">frog</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">cat</span> <span class="o">=</span> <span class="mi">3</span> <span class="c1"># Additional space before equals sign.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">frog</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">cat</span> <span class="o">=</span> <span class="mi">3</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p>Do not put a space either before or after the equals sign of a <a class="reference external" href="https://docs.python.org/3/tutorial/controlflow.html#tut-keywordargs" title="(in Python v3.14)"><span class="xref std std-ref">keyword
argument</span></a>. In this case, grouping the parameter name and
the argument is more important. This rule also creates a visual distinction between
assignment statements and keyword arguments.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">myfunction</span><span class="p">(</span><span class="n">arg1</span> <span class="o">=</span> <span class="n">val1</span><span class="p">,</span> <span class="n">arg2</span> <span class="o">=</span> <span class="n">val2</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">myfunction</span><span class="p">(</span><span class="n">arg1</span><span class="o">=</span><span class="n">val1</span><span class="p">,</span> <span class="n">arg2</span><span class="o">=</span><span class="n">val2</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p>Put exactly one space before and after the lowest priority
mathematical operators in an expression. This has the effect of
visually separating the terms of an expression, as we
conventionally do in mathematics.</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">y</span> <span class="o">=</span> <span class="mi">3</span><span class="o">*</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span><span class="o">+</span><span class="mi">4</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="mi">5</span> <span class="c1"># No spaces around +</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">y</span> <span class="o">=</span> <span class="mi">3</span><span class="o">*</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">4</span><span class="o">*</span><span class="n">x</span> <span class="o">+</span> <span class="mi">5</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
<li><p><strong>Never, ever</strong> have blank spaces at the end of a line, even a blank
line. These tend to get changed by editors, which results in lots
of spurious differences between otherwise identical code. This can
make the difference between two commits of a file very hard to read
indeed.</p></li>
</ol>
</section>
<section id="line-breaks">
<h3><span class="section-number">4.3.3. </span>Line breaks<a class="headerlink" href="#line-breaks" title="Link to this heading">¶</a></h3>
<ol class="arabic">
<li><p>Have no lines longer than 79 characters. Limiting the line length
makes lines easier to read, and prevents the editor from
automatically wrapping the line in harder to read ways. Shorter
lines are also very useful when using side-by-side differencing
tools to show the differences between two versions of a piece of
code.</p></li>
<li><p>When breaking lines to fit under 79 characters, it’s better to
break the lines using the implied continuation within round, square
or curly brackets than explicitly with a backslash. This is because
the brackets provide good visual “book ends” for the beginning and
end of the continuation. Of course this is sometimes impossible, so it is
occasionally necessary to use backslashes to break lines.</p></li>
<li><p>When a mathematical operator occurs at a line break, always put the
operator first on the next line, and not last on the first
line. Having the second line start with a mathematical operator
provides a solid visual clue that the next line is a continuation
of the previous line. (If you look closely, this is also the rule
that most publishers of maths books use).</p>
<blockquote>
<div><div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">my_function</span><span class="p">(</span><span class="n">first_term</span> <span class="o">+</span> <span class="c1"># Trailing + operator.</span>
<span class="n">second_term</span> <span class="o">+</span>
<span class="n">third_term</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">my_function</span><span class="p">(</span><span class="n">first_term</span>
<span class="o">+</span> <span class="n">second_term</span> <span class="c1"># Leading + operator</span>
<span class="o">+</span> <span class="n">third_term</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
</ol>
</section>
<section id="indentation">
<h3><span class="section-number">4.3.4. </span>Indentation<a class="headerlink" href="#indentation" title="Link to this heading">¶</a></h3>
<ol class="arabic">
<li><p>Indentation is <em>always</em> by four spaces per indentation level. Usually
Python-aware text editors are good at enforcing this, and this is basically
true of Visual Studio Code. If you’re using a text editor which doesn’t
indent by four spaces (especially if it uses <kbd class="kbd docutils literal notranslate">tab</kbd> characters for indentation)
then Google how to change it to four spaces!</p></li>
<li><p>When indenting continuation lines inside brackets, there are two
options, usually depending on how many characters are already on
the line before the opening bracket:</p>
<ol class="loweralpha simple">
<li><p>With one or more items on the first line after the opening
bracket. Subsequent lines are indented to one space more than
the opening bracket, so that the first items on each line start
exactly under each other. The closing bracket comes on the same
line as the final item.</p></li>
</ol>
<blockquote>
<div><div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">capitals</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"France"</span><span class="p">:</span> <span class="s2">"Paris"</span><span class="p">,</span>
<span class="s2">"China"</span><span class="p">:</span> <span class="s2">"Beijing"</span><span class="p">,</span>
<span class="s2">"Australia"</span><span class="p">:</span> <span class="s2">"Canberra"</span><span class="p">}</span>
</pre></div>
</div>
</div>
</div></blockquote>
<ol class="loweralpha simple" start="2">
<li><p>With the opening bracket as the last item on the first
line. Subsequent lines are indented more than the first line but
the same as each other. The closing bracket comes on a new line,
and is indented to the same level as the first line.</p></li>
</ol>
<blockquote>
<div><div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">capitals</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"Central African Republic"</span><span class="p">:</span> <span class="s2">"Bangui"</span><span class="p">,</span>
<span class="s2">"Trinidad and Tobago"</span><span class="p">:</span> <span class="s2">"Port of Spain"</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
</div></blockquote>
</li>
</ol>
</section>
</section>
<section id="names">
<h2><span class="section-number">4.4. </span>Names<a class="headerlink" href="#names" title="Link to this heading">¶</a></h2>
<p>Programs are full of names. Variables, classes, functions,
modules: much, perhaps most, of the text of a program is made up of
names. The choice of names, therefore, has a massive impact on the
readability of a program. There are two aspects to naming
conventions. One is a set of rules about the formatting of names: when
to use capitals, when underscores and so on. This is covered by PEP 8
and we reproduce some of the important rules below. The second aspect
is the choice of the letter, word, or words that make up a name. This
is much more a matter of judgement, though there are guiding principles
that greatly help with clarity.</p>
<section id="pep-8-name-conventions">
<h3><span class="section-number">4.4.1. </span>PEP 8 name conventions<a class="headerlink" href="#pep-8-name-conventions" title="Link to this heading">¶</a></h3>
<p>PEP 8 has some rather detailed rules for naming, including for
advanced cases that we are unlikely to encounter in the short term,
but the most important rules are short and clear:</p>
<dl>
<dt>class names</dt><dd><p>Class names use the CapWords convention: each word in a name is
capitalised and words are concatenated, without underscores between.</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">complex_polynomial</span> <span class="c1"># No capitals, underscore between words.</span>
<span class="n">complexPolynomial</span> <span class="c1"># Missing leading capital.</span>
<span class="n">Complex_Polynomial</span> <span class="c1"># Underscore between words.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">ComplexPolynomial</span>
</pre></div>
</div>
</div>
</dd>
<dt>exception names</dt><dd><p>Exceptions are classes, so the rules for class names apply with the
addition that exceptions that designate errors should end in
<code class="xref py py-obj docutils literal notranslate"><span class="pre">Error</span></code>.</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">PolynomialDivisionError</span> <span class="c1"># For example to indicate indivisibility.</span>
</pre></div>
</div>
</div>
</dd>
<dt>function, variable, and module names</dt><dd><p>Almost all names other than classes are usually written in all
lower case, with underscores separating words. Even proper nouns are
usually spelt with lower case letters to avoid being confused with
class names.</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">Euler</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># Don't capitalise function names.</span>
<span class="n">MaxRadius</span> <span class="o">=</span> <span class="mf">10.</span> <span class="c1"># No CamelCase.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">euler</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># Lower case, even for names.</span>
<span class="n">max_radius</span> <span class="o">=</span> <span class="mf">10.</span> <span class="c1"># Separate words with _.</span>
</pre></div>
</div>
</div>
</dd>
<dt>method parameters</dt><dd><p>The first parameter to an <a class="reference internal" href="3_objects.html#term-instance-method"><span class="xref std std-term">instance method</span></a> is the class
itself. <em>Always and without exception</em> name this parameter <code class="xref py py-obj docutils literal notranslate"><span class="pre">self</span></code>.</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyClass</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="n">instance</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyClass</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
</div>
</dd>
<dt>non-public methods and attributes</dt><dd><p>If a method or attribute is not intended to be directly accessed
from outside the class, it should have a name starting with an
underscore. This provides a clear distinction between the public
interface of a class and its internal implementation.</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyClass</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_internal_method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg1</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
</div>
</dd>
</dl>
</section>
<section id="choosing-names">
<h3><span class="section-number">4.4.2. </span>Choosing names<a class="headerlink" href="#choosing-names" title="Link to this heading">¶</a></h3>
<p>Short names help make short lines of code, which in turn makes it easier
to read and understand what the code does to the values it is
operating on. However short names can also be cryptic, making it
difficult to establish what the names mean. This creates a tension:
should names be short to create readable code, or long and descriptive
to clarify their meaning?</p>
<p>A good answer to this dilemma is that local variables should have
short names. These are often the most frequently occurring variables on
a line of code, which makes the statement more
intelligible. Should a reader be unclear what a variable stands for,
the definition of a local variable will not be very far
away. Conversely, a module, class, or function which might be used
far from its definition had better have a descriptive name which makes
its purpose immediately apparent.</p>
</section>
<section id="follow-the-mathematics">
<h3><span class="section-number">4.4.3. </span>Follow the mathematics<a class="headerlink" href="#follow-the-mathematics" title="Link to this heading">¶</a></h3>
<p>Remember that the key objective of code style conventions is to make
it easier for readers to understand the code. If the code implements a
mathematical algorithm, then it’s quite likely that readers of that
code will have at least a passing acquaintance with that area of
mathematics. You will therefore greatly help their intuition for what
your code does if the names in the code match the mathematical
conventions for the same concepts. You can use underscores to hint at
subscripts, just like in LaTeX. For example, if you write a function
which changes coordinates, then <code class="xref py py-obj docutils literal notranslate"><span class="pre">x_old</span></code> and <code class="xref py py-obj docutils literal notranslate"><span class="pre">x_new</span></code> are likely to be
good names for the coordinate vector before and after the
transformation.</p>
<p>As an exception to the rules about variable case, it is a good idea to
use single capital letter names in circumstances where they would be
used in the maths, for example, to name a matrix.</p>
<p>Mathematicians often use Greek letters as variable names,
occasionally they venture further afield and use Cyrillic or Hebrew
letters. Python does allow for variable names written in other
alphabets, but these are hard to type on many keyboards. Someone
trying to fix bugs in your code will curse you if they can’t even type
the names! Do, by all means, use Greek or other language variable
names where this will make the relationship between the maths and the
code obvious, but write out the Greek letter name in Roman
letters. For example, <code class="xref py py-obj docutils literal notranslate"><span class="pre">theta</span></code> is a very good name for a variable
representing an angle. Capital Greek letters are sometimes represented
by capitalising the first letter of the Roman word, but take care to
avoid situations where this might be confused for a class name.</p>
</section>
<section id="enforcing-name-conventions-in-flake8">
<h3><span class="section-number">4.4.4. </span>Enforcing name conventions in Flake8<a class="headerlink" href="#enforcing-name-conventions-in-flake8" title="Link to this heading">¶</a></h3>
<p>The core Flake8 package does not enforce the PEP 8 naming conventions, but there
is a plugin which does so. Simply install the <code class="xref py py-mod docutils literal notranslate"><span class="pre">pep8-naming</span></code> package.</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>-m<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>pep8-naming
</pre></div>
</div>
</section>
</section>
<section id="parsimony">
<h2><span class="section-number">4.5. </span>Parsimony<a class="headerlink" href="#parsimony" title="Link to this heading">¶</a></h2>
<p>Good programming style is primarily about making programmes easy to
understand. One of the key limitations of understanding is the sheer
number of objects that the reader can keep in their short term memory
at once. Without diverting into the psychology literature, this is
only a couple of handfuls of values at most. This means that the
largest amount of code that a reader can actively reason about is
limited to a few operations on a few variables. As a programmer, there
are two tools at your disposal to achieve this. The first is to be
parsimonious and not introduce unnecessary temporary variables. The
second is to use abstractions such as classes and function interfaces
to split the problem up into small pieces so that each individual
function or method is small enough for a reader to understand.</p>
<p>As a (somewhat contrived) example, assume that you need to create a list of all
the positive integers less than 9999 which are divisible by all the numbers up
to seven. You could write this in 5 difficult to understand lines:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9999</span><span class="p">):</span>
<span class="k">if</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">1</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span> \
<span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">6</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">_</span> <span class="o">%</span> <span class="mi">7</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_</span><span class="p">)</span>
</pre></div>
</div>
</div>
<p>It would be much better to write a single more abstract but simpler line:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">num</span> <span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9999</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">all</span><span class="p">(</span><span class="n">num</span> <span class="o">%</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">))]</span>
</pre></div>
</div>
</div>
<section id="use-comprehensions">
<h3><span class="section-number">4.5.1. </span>Use comprehensions<a class="headerlink" href="#use-comprehensions" title="Link to this heading">¶</a></h3>
<p>It is very common to write loops to populate collection objects with
values. For example, we might make a list of the first 10 square
numbers for further use:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">squares</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">squares</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
</div>
<p>This is a fairly typical, if simple, example. It takes three lines of
code: one to initialise the list, one to loop, and one to add the
values to the list. Alternatively, if we had used a <a class="reference external" href="https://docs.python.org/3/tutorial/datastructures.html#tut-listcomps" title="(in Python v3.14)"><span class="xref std std-ref">list
comprehension</span></a>, all three steps would have been subsumed into a single
operation:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">squares</span> <span class="o">=</span> <span class="p">[(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)]</span>
</pre></div>
</div>
</div>
<p>At least for fairly simple operations, comprehensions are almost
always easier for the reader to understand than loops. In addition to
lists, comprehensions are also available for <a class="reference external" href="https://docs.python.org/3/tutorial/datastructures.html#tut-sets" title="(in Python v3.14)"><span class="xref std std-ref">sets</span></a>
and <a class="reference external" href="https://docs.python.org/3/tutorial/datastructures.html#tut-dictionaries" title="(in Python v3.14)"><span class="xref std std-ref">dictionaries</span></a>.</p>
</section>
<section id="redundant-logical-expressions">
<h3><span class="section-number">4.5.2. </span>Redundant logical expressions<a class="headerlink" href="#redundant-logical-expressions" title="Link to this heading">¶</a></h3>
<p>One exceptionally common failure of parsimony is to write expressions of the following form:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">var</span> <span class="o">==</span> <span class="kc">True</span><span class="p">:</span>
</pre></div>
</div>
</div>
<p>To see the problem with this statement, let’s write out its truth table:</p>
<table class="center-align-center-col docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">var</span></code></p></th>
<th class="head"><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">var</span> <span class="pre">==</span> <span class="pre">True</span></code></p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>T</p></td>
<td><p>T</p></td>
</tr>
<tr class="row-odd"><td><p>F</p></td>
<td><p>F</p></td>
</tr>
</tbody>
</table>
<p>In other words, the expressions <code class="xref py py-obj docutils literal notranslate"><span class="pre">var</span></code> and <code class="xref py py-obj docutils literal notranslate"><span class="pre">var</span> <span class="pre">==</span> <span class="pre">True</span></code> are logically
equivalent (at least assuming <code class="xref py py-obj docutils literal notranslate"><span class="pre">var</span></code> is a <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#bltin-boolean-values" title="(in Python v3.14)"><span class="xref std std-ref">boolean value</span></a>), so it would
have been more parsimonious to write:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">var</span><span class="p">:</span>
</pre></div>
</div>
</div>
<p>Similarly:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">var</span> <span class="o">==</span> <span class="kc">False</span><span class="p">:</span>
</pre></div>
</div>
</div>
<p>is frowned upon by programmers in favour of:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="ow">not</span> <span class="n">var</span><span class="p">:</span>
</pre></div>
</div>
</div>
<p>Finally, the use of <a class="reference external" href="https://docs.python.org/3/reference/compound_stmts.html#else" title="(in Python v3.14)"><span class="xref std std-ref">else</span></a> (or <a class="reference external" href="https://docs.python.org/3/reference/compound_stmts.html#elif" title="(in Python v3.14)"><span class="xref std std-ref">elif</span></a>) can reduce the number
of logical expressions that the reader has to read and
understand. This means that:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">var</span><span class="p">:</span>
<span class="c1"># Some code</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">var</span><span class="p">:</span>
<span class="c1"># Some other code</span>
</pre></div>
</div>
</div>
<p>should be avoided in favour of:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">var</span><span class="p">:</span>
<span class="c1"># Some code</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Some other code.</span>
</pre></div>
</div>
</div>
<p>In addition to having fewer logical operations which the reader needs
to understand, the <code class="xref py py-obj docutils literal notranslate"><span class="pre">if...else</span></code> version explicitly ties
the two cases together as alternatives, which is an additional aid to
comprehension.</p>
</section>
<section id="use-the-fact-that-every-object-is-true-or-false">
<h3><span class="section-number">4.5.3. </span>Use the fact that every object is True or False<a class="headerlink" href="#use-the-fact-that-every-object-is-true-or-false" title="Link to this heading">¶</a></h3>
<p>Every Python object is logically either <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a> or <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a> according to the
following rules:</p>
<ol class="arabic simple">
<li><p><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">None</span></code></a> is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a>.</p></li>
<li><p>Zero is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a>, all other numerical values are <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a>.</p></li>
<li><p>An empty collection is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a>, any other container is <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a>. For
example, an empty list is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a>, but the list <code class="xref py py-obj docutils literal notranslate"><span class="pre">[0,</span> <span class="pre">0]</span></code> is <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a>.</p></li>
<li><p>The null string <code class="xref py py-obj docutils literal notranslate"><span class="pre">""</span></code> is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a>, a string containing any characters is <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a>.</p></li>
<li><p>A user-defined class is <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a> unless:</p>
<ol class="loweralpha simple">
<li><p>It defines the <a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#object.__bool__" title="(in Python v3.14)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__bool__()</span></code></a> <a class="reference internal" href="3_objects.html#term-special-method"><span class="xref std std-term">special
method</span></a>. In this case the truth value is whatever this method
returns.</p></li>
<li><p>It doesn’t define <a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#object.__bool__" title="(in Python v3.14)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__bool__()</span></code></a> but does define
<a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#object.__len__" title="(in Python v3.14)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__len__()</span></code></a>. In this case the object is <a class="reference external" href="https://docs.python.org/3/library/constants.html#False" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">False</span></code></a> if the
length is zero, and <a class="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.14)"><code class="xref py py-data docutils literal notranslate"><span class="pre">True</span></code></a> otherwise.</p></li>
</ol>
</li>
</ol>
<p>These rules are laid out formally in <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#truth" title="(in Python v3.14)"><span class="xref std std-ref">the Python documentation</span></a>. One way that they can be used to write simpler, clearer code
is in the very common case of code that should only execute if a
collection object actually contains something. In that case, this form
of test is to be preferred:</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">mysequence</span><span class="p">:</span>
<span class="c1"># Some code using mysequence</span>
</pre></div>
</div>
</div>
<p>instead of:</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">mysequence</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="c1"># Some code using mysequence</span>
</pre></div>
</div>
</div>
</section>
<section id="avoid-repetition">
<span id="repetition"></span><h3><span class="section-number">4.5.4. </span>Avoid repetition<a class="headerlink" href="#avoid-repetition" title="Link to this heading">¶</a></h3>
<p>Programmers very frequently need to do <em>nearly</em> the same thing over and over.
One obvious way to do this is to write code for the first case, then copy and
paste the code for subsequent cases, making changes as required. There are a
number of significant problems with this approach. First, it multiplies the
amount of code that a reader has to understand, and does so in a particularly
pernicious way. A reader will effectively have to play “spot the difference”
between the different code versions, and hope they don’t miss something. Second,
it makes it incredibly easy for to get confused about which version of the code
a programmer is supposed to be working on. There are few things more frustrating
than attempting to fix a bug and repeatedly seeing that nothing changes, only to
discover hours (or days) later that you have been working on the wrong piece of
nearly-identical code. Finally, lets suppose that a bug is fixed - what happens
to the near-identical clones of that code? The chance is very high that the bug
stays unfixed in those versions thereby creating yet another spot the difference
puzzle for the next person encountering a bug.</p>
<p>Abstractions are essentially tools for removing harmful repetition. For
example, it may be possible to bundle up the repeated code in a function or
class, and to encode the differences between versions in the <a class="reference external" href="https://docs.python.org/3/glossary.html#term-parameter" title="(in Python v3.14)"><span class="xref std std-term">parameters</span></a> to the function or class constructor. If the differences between
the versions of the code require different code, as opposed to different values
of some quantities, then it may be possible to use <a class="reference internal" href="7_inheritance.html#term-inheritance"><span class="xref std std-term">inheritance</span></a> to avoid
repetition. We will return to this in <a class="reference internal" href="7_inheritance.html#inheritance"><span class="std std-numref">Chapter 7</span></a>.</p>
</section>
</section>
<section id="comments">
<h2><span class="section-number">4.6. </span>Comments<a class="headerlink" href="#comments" title="Link to this heading">¶</a></h2>
<p>Comments are non-code text included in programs to help explain what
they do. Since comments exist to aid understanding, some programmers
come to the conclusion that more comments imply more
understanding. Indeed, some programmers are even taught that every
line of code should have a comment. This could not be more wrong!</p>
<p>While judiciously deployed comments can be an essential aid to
understanding, too many comments can be worse than too few. If the
code is simple, elegant, and closely follows how a reader would expect
the algorithm to be written, then it will be readily understood
without comments. Conversely, attempting to rescue obscure, badly
thought-through code by writing about it is unlikely to remedy the
situation.</p>
<p>A further severe problem with comments is that they can easily become
out of date. If a piece of code is modified, it is all too easy for the
programmer to neglect to update accompanying comments. The result is
comments which explain one thing, code which does something else, and
exceptionally baffled readers.</p>
<section id="three-rules-for-commenting">
<h3><span class="section-number">4.6.1. </span>Three rules for commenting<a class="headerlink" href="#three-rules-for-commenting" title="Link to this heading">¶</a></h3>
<ol class="arabic simple">
<li><p>If code is so simple, clear, and obvious that it can be easily
understood without comments, don’t comment.</p></li>
<li><p>If code is not easily understood without comments, the problem is
probably the code. Refactor the code to be simpler and easier to
understand.</p></li>
<li><p>If, and only if, you are convinced that it is strictly necessary to do
something unobvious, then do so and include a comment.</p></li>
</ol>
</section>
<section id="comment-why-not-what">
<h3><span class="section-number">4.6.2. </span>Comment why, not what<a class="headerlink" href="#comment-why-not-what" title="Link to this heading">¶</a></h3>
<p>Even where a comment is unavoidable, it should still usually be
obvious <em>what</em> it is that code does. It is far more likely to be
justifiable to include a comment about <em>why</em> a particular approach is
taken. For example, it might be worth commenting why an apparently
simpler alternative strategy is actually invalid.</p>
</section>
<section id="pep-8-rules-for-comments">
<h3><span class="section-number">4.6.3. </span>PEP 8 rules for comments<a class="headerlink" href="#pep-8-rules-for-comments" title="Link to this heading">¶</a></h3>
<p>Comments start with a single <code class="file docutils literal notranslate"><span class="pre">#</span></code> followed by a single space.
<a class="reference internal" href="#term-inline-comment"><span class="xref std std-term">Inline comments</span></a> are separated from the code by at
least two spaces.</p>
<div class="badcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span><span class="c1"># No space between code and comment.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1">#No space between # and comment text.</span>
</pre></div>
</div>
</div>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># Two spaces before #, one after.</span>
</pre></div>
</div>
</div>
<p>Each line of a block comment starts with a single <code class="file docutils literal notranslate"><span class="pre">#</span></code> indented to the
same level as a normal line of code. The <code class="file docutils literal notranslate"><span class="pre">#</span></code> is followed by a single
space, unless a particular piece of comment should be indented with respect to
the paragraph it is in, in which case additional spaces are allowed.</p>
<div class="goodcode docutils container">
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">somecondition</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="c1"># Comment indented to the same level as the contents of the if</span>
<span class="c1"># block.</span>
</pre></div>
</div>
</div>
</section>
</section>
<section id="docstrings">
<h2><span class="section-number">4.7. </span>Docstrings<a class="headerlink" href="#docstrings" title="Link to this heading">¶</a></h2>
<p>There is one enormous exception to the rule that comments should be
used only sparingly: docstrings. Docstrings (a portmanteau of
“documentation strings”) are comments at the start of modules,
classes, and functions which describe public interfaces. The entire
point of a public interface is that the programmer using it should not
have to concern themselves with how it is implemented. They should,
therefore, not need to read the code in order to understand how to use
it.</p>
<p>The <a class="reference internal" href="2_programs_in_files.html#term-Python-interpreter"><span class="xref std std-term">Python interpreter</span></a> has special support for docstrings. When a user
calls <a class="reference external" href="https://docs.python.org/3/library/functions.html#help" title="(in Python v3.14)"><code class="xref py py-func docutils literal notranslate"><span class="pre">help()</span></code></a> on an <a class="reference external" href="https://docs.python.org/3/glossary.html#term-object" title="(in Python v3.14)"><span class="xref std std-term">object</span></a> (including a function or <a class="reference internal" href="3_objects.html#term-method"><span class="xref std std-term">method</span></a>)
then any docstring on that object is used as the body of the resulting help
message. Docstrings are also understood by the Python documentation generation
system, <a class="reference external" href="https://www.sphinx-doc.org/en/master/">Sphinx</a>. This enables
documentation webpages to be automatically generated from Python code. The
Python documentation in this course is generated by this system. For example,
recall that we met the function <a class="reference internal" href="fibonacci.html#fibonacci.fibonacci.fib" title="fibonacci.fibonacci.fib"><code class="xref py py-func docutils literal notranslate"><span class="pre">fib()</span></code></a>, which
calculates Fibonacci numbers, in <a class="reference internal" href="2_programs_in_files.html#modules"><span class="std std-numref">Section 2.3</span></a>. We can ask
<a class="reference internal" href="fibonacci.html#fibonacci.fibonacci.fib" title="fibonacci.fibonacci.fib"><code class="xref py py-func docutils literal notranslate"><span class="pre">fib()</span></code></a> for its documentation:</p>
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span><span class="gp">In [1]: </span><span class="kn">import</span><span class="w"> </span><span class="nn">fibonacci</span>
<span class="gp">In [2]: </span><span class="n">help</span><span class="p">(</span><span class="n">fibonacci</span><span class="o">.</span><span class="n">fib</span><span class="p">)</span>
</pre></div>
</div>
<p>The following is displayed:</p>
<blockquote>
<div><p>Help on function fib in module fibonacci.fibonacci:</p>
<dl class="simple">
<dt>fib(n)</dt><dd><p>Return the n-th Fibonacci number.</p>
</dd>
</dl>
</div></blockquote>
<p>There is also a specific IPython help extension, which also works in Jupyter
notebooks (IPython and Jupyter are related projects). Appending a question mark
<kbd class="kbd docutils literal notranslate">?</kbd> to an object name prints a slightly different version of the help
information:</p>
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span><span class="gp">In [3]: </span>fibonacci.fib<span class="o">?</span>
<span class="go">Signature: fibonacci.fib(n)</span>
<span class="go">Docstring: Return the n-th Fibonacci number.</span>
<span class="go">File: ~/docs/principles_of_programming/object-oriented-programming/fibonacci/fibonacci.py</span>
<span class="go">Type: function</span>
</pre></div>
</div>
<p>Finally, the same information is used in the <a class="reference internal" href="fibonacci.html#fibonacci.fibonacci.fib" title="fibonacci.fibonacci.fib"><code class="xref py py-func docutils literal notranslate"><span class="pre">web</span> <span class="pre">documentation</span></code></a>. Notice that the <a class="reference internal" href="#term-function-signature"><span class="xref std std-term">function signature</span></a> is
not a part of the docstring. Python is capable of extracting the signature
of the function and adding it into the documentation without the programmer
having to manually add it to the docstring.</p>
<section id="where-to-use-docstrings">
<h3><span class="section-number">4.7.1. </span>Where to use docstrings<a class="headerlink" href="#where-to-use-docstrings" title="Link to this heading">¶</a></h3>
<p>Every public module, class, function, and method should have a docstring.
“Public” in this context means any code which is intended to be accessed from
outside the <a class="reference internal" href="2_programs_in_files.html#modules"><span class="std std-ref">module</span></a> in which it is defined.</p>
</section>
<section id="docstring-conventions">
<h3><span class="section-number">4.7.2. </span>Docstring conventions<a class="headerlink" href="#docstring-conventions" title="Link to this heading">¶</a></h3>
<p>Python itself doesn’t know anything about docstring contents, it will simply
display the docstring when you ask for help. However, other tools such as those
that generate websites from documentation depend on you following the
conventions.</p>
<p>By convention, docstrings are delimited by three double quote characters (<code class="xref py py-obj docutils literal notranslate"><span class="pre">"""</span></code>).</p>
</section>
<section id="short-docstrings">
<h3><span class="section-number">4.7.3. </span>Short docstrings<a class="headerlink" href="#short-docstrings" title="Link to this heading">¶</a></h3>
<p>Simple functions which take one or two arguments can be documented with a single
line docstring which simply says what the function does. The Fibonacci example above