forked from mikeckennedy/talk-python-transcripts
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy path018_quantifiedcode.vtt
More file actions
2153 lines (1435 loc) · 67.1 KB
/
018_quantifiedcode.vtt
File metadata and controls
2153 lines (1435 loc) · 67.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
WEBVTT
00:00:00.001 --> 00:00:03.660
Often, the most important lessons we learn are what not to do.
00:00:03.660 --> 00:00:09.520
Today, we'll be talking about bad Python code and Python anti-patterns with Andreas Duvez.
00:00:09.520 --> 00:00:13.600
It's show number 18, recorded Thursday, July 1st, 2015.
00:00:13.600 --> 00:00:43.580
Welcome to Talk Python To Me, a weekly podcast on Python, the language, the library,
00:00:43.760 --> 00:00:45.260
the ecosystem, and the personalities.
00:00:45.260 --> 00:00:46.880
This is your host, Michael Kennedy.
00:00:46.880 --> 00:00:49.000
Follow me on Twitter, where I'm @mkennedy.
00:00:49.000 --> 00:00:53.100
Keep up with the show and listen to past episodes at talkpythontome.com,
00:00:53.100 --> 00:00:55.660
and follow us on Twitter, where we're at Talk Python.
00:00:55.660 --> 00:01:02.220
This episode, we'll be talking to Andreas Duvez from Quantified Code about Python anti-patterns.
00:01:02.220 --> 00:01:06.660
This episode is brought to you by CodeShip and Hired.
00:01:06.660 --> 00:01:13.060
Thank them for supporting the show on Twitter via at CodeShip and at Hired underscore HQ.
00:01:13.560 --> 00:01:19.020
I don't have any major news for you this week, so let me introduce Andreas so we can get right to the show.
00:01:19.020 --> 00:01:23.840
Andreas is a physicist and software developer with a passion for code quality.
00:01:23.840 --> 00:01:27.600
He leads the development of algorithms and software at Quantified Code.
00:01:27.600 --> 00:01:29.760
Andreas, welcome to the show.
00:01:29.760 --> 00:01:30.880
Thanks.
00:01:30.880 --> 00:01:31.980
Thanks for having me here.
00:01:32.480 --> 00:01:33.780
It's great to have you here.
00:01:33.780 --> 00:01:40.880
We're going to talk about design patterns, both good design patterns and bad design patterns or anti-patterns,
00:01:40.880 --> 00:01:43.580
with the stuff you guys have going on at Quantified Code.
00:01:43.580 --> 00:01:44.820
Exactly.
00:01:44.820 --> 00:01:50.700
So you've built a bunch of awesome tools, both visual and static analysis, and we're going to talk about that.
00:01:50.700 --> 00:01:55.060
But before we get into it, let's just take a step back down memory lane and, you know,
00:01:55.060 --> 00:01:58.460
tell everyone how you got started in Python and programming and what's your story?
00:01:58.500 --> 00:01:59.020
How did you get here?
00:01:59.020 --> 00:02:03.640
So my background is actually not in software development, but in physics.
00:02:04.460 --> 00:02:10.360
And I made my first contact with Python while I was doing my PhD, which was about, like,
00:02:10.360 --> 00:02:12.520
experimental quantum computing.
00:02:12.520 --> 00:02:19.420
So we did experiments with microwaves and lots of signal processing.
00:02:19.420 --> 00:02:25.880
And when I arrived at our lab, we had, like, a lot of equipment that we needed to, like, control
00:02:25.880 --> 00:02:31.520
using programs, and we had a lot of data that we needed to analyze, to visualize, and to process.
00:02:32.160 --> 00:02:38.320
And we did that using various programming languages, for example, Matlab and C and C++.
00:02:38.320 --> 00:02:46.720
And we were also using tools like LabVIEW that help you to, like, define interfaces, graphical user
00:02:46.720 --> 00:02:50.080
things, and, like, control your measurement equipment.
00:02:50.080 --> 00:02:57.580
And then I remember when I came to the lab, this was basically a huge mess because we used, like,
00:02:57.580 --> 00:03:04.540
four different programming languages and the graphical programming interface of LabVIEW, which is nice in principle,
00:03:04.540 --> 00:03:09.260
but which makes it really, really difficult to write complex software systems with that.
00:03:09.600 --> 00:03:13.080
And so I said, hey, there has to be a better way to do this.
00:03:13.080 --> 00:03:19.960
And one of our postdocs, he used Python in his job in the U.S., and he introduced me to it.
00:03:19.960 --> 00:03:26.460
And so I started, like, getting interested in that, and I tried to, like, replace more and more of our software stack with Python.
00:03:26.960 --> 00:03:37.060
And after about one year or half a year, I think, we had replaced most of the data acquisition and data analysis things we had in the lab with Python programs.
00:03:37.480 --> 00:03:41.120
So that was kind of, like, the first contact with me, for me, with that language.
00:03:41.120 --> 00:03:48.200
And also when I, like, that I saw that it's really powerful and you can basically do anything with it.
00:03:48.200 --> 00:03:49.640
And, yeah.
00:03:49.640 --> 00:03:51.060
Yeah, that's great.
00:03:51.060 --> 00:03:55.620
I think a lot of people come to Python for the data science component of it.
00:03:55.620 --> 00:04:06.980
And I think, like you were saying, the fact that it's a full stack, legitimate, end-to-end programming language means you don't have to just live within those little shells of what MATLAB will do or LabVIEW will do.
00:04:07.060 --> 00:04:08.440
But you can bring it all together.
00:04:08.440 --> 00:04:09.320
Yes, exactly.
00:04:09.320 --> 00:04:10.100
Yeah.
00:04:10.100 --> 00:04:15.040
And, I mean, back in 2009, when I started using it, the tooling was already pretty good.
00:04:15.040 --> 00:04:23.700
But if you have a look at it now in 2015, it's really amazing what kind of an ecosystem people have created.
00:04:23.700 --> 00:04:32.620
You know, for example, the IPython notebook, NumPy, SciPy, and all these other tools that we can use to, as you say, do almost anything that we can imagine.
00:04:32.620 --> 00:04:35.280
So it's really, really amazing to see.
00:04:35.280 --> 00:04:36.760
Yeah, it is really amazing.
00:04:36.880 --> 00:04:38.400
And it's great.
00:04:38.400 --> 00:04:42.480
And I think the thing that, among other things, that surprises me is it's free.
00:04:42.480 --> 00:04:47.940
You look at MATLAB and Mathematica, you pay tons of money to be locked into these, like, somewhat confusing.
00:04:47.940 --> 00:04:48.460
Yeah, exactly.
00:04:48.460 --> 00:04:50.900
And it's the power of open source.
00:04:50.900 --> 00:04:52.640
So I think, yeah.
00:04:52.980 --> 00:04:57.300
You're doing all this cool programming and getting into Python for your work at Quantified Code.
00:04:57.300 --> 00:04:58.860
This is a company you co-founded.
00:04:58.860 --> 00:04:59.880
Who do you co-found it with?
00:04:59.880 --> 00:05:00.900
And what do you guys do there?
00:05:01.700 --> 00:05:04.360
So I co-founded it with an old friend of mine.
00:05:04.360 --> 00:05:09.080
And we're doing static code analysis for Python, but also other programming languages.
00:05:09.800 --> 00:05:18.860
And the reason we started this company was that I saw during my PhD that, hey, it's really hard to write good software because I didn't have a background in software development.
00:05:18.860 --> 00:05:21.440
So I wrote lots of very, very bad code.
00:05:21.640 --> 00:05:23.260
And I made a lot of mistakes.
00:05:23.260 --> 00:05:29.140
And I thought it would be really nice to have, like, a system, an automated system that would tell me how to write good code.
00:05:29.140 --> 00:05:32.720
So that's when I got interested in all these things like static code analysis.
00:05:32.720 --> 00:05:37.800
And I started looking into what kind of tools existed for Python and other languages.
00:05:37.800 --> 00:05:43.340
And I found that most of the tools that we're using today are still not good enough or they could be much better.
00:05:43.480 --> 00:05:53.240
And so that's kind of our mission to, like, make these tools much better and allow anyone to, like, have access to really high-quality, state-of-the-art code analysis.
00:05:53.240 --> 00:05:54.780
Yeah, that's great.
00:05:54.780 --> 00:05:59.820
One of the problems with a lot of static code analysis is it's very good at finding the small rules.
00:05:59.820 --> 00:06:03.020
Like, hey, you should have white space between these things.
00:06:03.020 --> 00:06:04.860
You should have a new line here.
00:06:04.860 --> 00:06:06.320
Your line shouldn't be this long.
00:06:06.320 --> 00:06:07.700
Your variables should be named this way.
00:06:07.700 --> 00:06:08.180
Yeah, exactly.
00:06:08.180 --> 00:06:10.860
But that's, like, the stuff that robots can do, you know?
00:06:10.860 --> 00:06:17.940
The stuff that's really valuable is the hard-learned lessons of if you write your code this way, it's easier to maintain.
00:06:17.940 --> 00:06:22.300
If you write your code that way, it will actually run faster or it will be less error-prone.
00:06:22.300 --> 00:06:28.780
And that's normally what you get by working with kind of a mentoring apprenticeship, you know, working in a team.
00:06:28.780 --> 00:06:32.840
But it's also the whole concept of design patterns, right?
00:06:32.840 --> 00:06:34.340
Yes, exactly.
00:06:34.340 --> 00:06:43.680
I mean, design patterns certainly help people to become productive and to use solutions that are better proven, so to say, and tested in the field.
00:06:43.680 --> 00:06:50.420
I mean, a design pattern in that sense is just like a reusable solution that you can take and implement in your own code.
00:06:51.280 --> 00:06:59.760
And, I mean, I wasn't even aware of that, but I also made use of design patterns, which are covered, like, from the internet for the work I did during my PhD.
00:06:59.760 --> 00:07:13.080
I used, for example, the observer pattern and the command pattern and other things, which I just, like, yeah, intuitively could adapt to my own needs and use in my projects.
00:07:13.260 --> 00:07:27.000
And the great thing about this is also that it gives you, like, a common language to talk to other people, you know, because if you say, hey, I got this class, which is, like, receiving a notification from this other class and then I was doing some things.
00:07:27.000 --> 00:07:33.520
I mean, it's okay, but you could just say, hey, I'm using this observer class and then everyone kind of knows what you mean, you know?
00:07:33.740 --> 00:07:39.240
Yeah, I think that is one of the absolute really strong powers of design patterns.
00:07:39.240 --> 00:07:46.380
Obviously, one is to know the solutions, but the other is to have larger building blocks as you think about your application mentally.
00:07:46.380 --> 00:07:47.100
Yes, exactly.
00:07:47.100 --> 00:07:47.820
All right.
00:07:47.820 --> 00:07:53.900
Like you say, if I go to you and I describe, okay, what I'm going to do is I'm going to have a variable and the variable is going to be shared.
00:07:53.900 --> 00:07:57.920
There's only going to be one of them and it's going to be shared across all parts of the application.
00:07:57.920 --> 00:08:05.260
And so when one part changes it, the other part will see that same change, I could have this conversation or I could just say I'm using the singleton pattern.
00:08:05.260 --> 00:08:06.240
Yes, exactly.
00:08:06.240 --> 00:08:07.780
You know what I'm talking about.
00:08:07.780 --> 00:08:09.600
You know what the positive side of that is.
00:08:09.600 --> 00:08:11.020
You know what the negative side of that is.
00:08:11.020 --> 00:08:14.180
You know singleton pattern is a challenge for unit testing.
00:08:14.180 --> 00:08:16.480
And so is that a tradeoff you want to make?
00:08:16.480 --> 00:08:19.340
And it's not just helpful for working in a team.
00:08:19.340 --> 00:08:20.300
I can tell you that.
00:08:20.300 --> 00:08:21.440
You could tell me that.
00:08:21.440 --> 00:08:26.120
But I think it's also helpful just for you internally as you think about how your code is structured.
00:08:26.120 --> 00:08:27.720
Yeah, absolutely.
00:08:27.720 --> 00:08:32.580
We've all written a lot of code and we may or may have not given it good attention.
00:08:32.580 --> 00:08:34.880
We may have written it bad.
00:08:34.880 --> 00:08:36.080
We may have written it well.
00:08:36.080 --> 00:08:37.180
We might have been in a hurry.
00:08:37.180 --> 00:08:41.540
And so, or, you know, much more common, we've gotten it from somebody else.
00:08:41.540 --> 00:08:43.580
And we have to deal with it.
00:08:43.580 --> 00:08:50.520
And I think understanding these design patterns is really interesting, but also understanding when they're needed.
00:08:50.940 --> 00:08:55.780
And so there's this related idea of this concept called code smells.
00:08:55.780 --> 00:08:59.080
I think it was introduced by Martin Fowler, but I'm not entirely sure.
00:08:59.080 --> 00:08:59.680
Are you familiar with it?
00:08:59.680 --> 00:09:00.340
Yes, it's possible.
00:09:00.340 --> 00:09:00.600
Yeah.
00:09:01.100 --> 00:09:02.600
I'm not 100% sure.
00:09:02.600 --> 00:09:09.920
I mean, design patterns has been introduced by this gang of four in 1994, but I'm not sure where the term code smells comes from.
00:09:10.440 --> 00:09:12.800
Yeah, certainly Martin Fowler wrote a lot about it.
00:09:12.800 --> 00:09:16.580
And I think it's a very interesting way to think of things.
00:09:16.580 --> 00:09:20.880
So I'll put a link to some code smells in the show notes.
00:09:20.880 --> 00:09:24.940
And I think kind of what your code does is it sort of looks for code smells.
00:09:24.940 --> 00:09:30.380
It says you're doing these things that are not necessarily going to make your code not run, but it's not the best way to do it.
00:09:30.380 --> 00:09:31.660
Yes, exactly.
00:09:31.660 --> 00:09:43.120
I mean, what a static code analyzer does is basically that it looks for patterns in the code that can either produce bugs or are quality problems of the code.
00:09:43.420 --> 00:09:49.680
And so for us, like code smell can be categorized by how severe it is.
00:09:49.680 --> 00:09:57.300
So it might make your code crash or it might just be an annoyance to another programmer who takes longer to understand the code.
00:09:57.300 --> 00:10:01.740
And also by various categories like does it affect the performance?
00:10:01.740 --> 00:10:03.900
Does it affect the security of the code?
00:10:03.900 --> 00:10:05.400
Does it affect the maintainability?
00:10:05.400 --> 00:10:09.900
So there are lots of lots of different types of code smells in that sense.
00:10:10.120 --> 00:10:18.900
Yeah, and if you think back, you know, just thinking of the code smells that I can remember, there's some good ones like duplicated code.
00:10:18.900 --> 00:10:20.060
Oh, yeah.
00:10:20.060 --> 00:10:22.100
That one's common, right?
00:10:22.100 --> 00:10:23.080
Yes.
00:10:23.080 --> 00:10:27.960
Or feature envy or, you know, long method.
00:10:27.960 --> 00:10:31.260
Or there's a bunch of, you know, too many parameters.
00:10:32.260 --> 00:10:32.580
Yes.
00:10:32.580 --> 00:10:35.420
I mean, this we're seeing a lot in the code we analyze.
00:10:35.420 --> 00:10:43.360
Very complex functions, a lot of parameters that have too many responsibilities and are really hard to understand.
00:10:43.360 --> 00:10:50.840
So, I mean, I think that's really the number one performance or maintainability killer today in software complexity.
00:10:51.120 --> 00:10:51.460
I agree.
00:10:51.460 --> 00:10:57.400
One of the really interesting code smells, I think, are comments.
00:10:57.400 --> 00:11:00.880
And so you think, you know, comments, I'm supposed to comment my code.
00:11:00.880 --> 00:11:01.660
That's a good thing.
00:11:01.660 --> 00:11:06.880
A lot of times programmers will use comments where they should have just written better code.
00:11:06.880 --> 00:11:07.960
Yes, exactly.
00:11:07.960 --> 00:11:11.740
They'll write a function that has a bad name and it's not well written.
00:11:11.740 --> 00:11:12.680
So it's hard to understand.
00:11:12.680 --> 00:11:27.860
And it'll put a nice little comment to describe what it does because it's not well written, you know, where the real fix would be to write a well, to refactor, to have a proper descriptive name and to be cleaner in smaller parts, right?
00:11:27.860 --> 00:11:28.700
Yeah, absolutely.
00:11:28.700 --> 00:11:29.320
Yeah.
00:11:29.320 --> 00:11:32.540
Comments are kind of like deodorant for code smells, right?
00:11:32.540 --> 00:11:34.280
That's a good conversion, yeah.
00:11:35.100 --> 00:11:45.160
Okay, so that brings us to how I kind of got connected to you guys or learned about you guys is through this thing you wrote called The Little Book of Python Anti-Patterns.
00:11:45.160 --> 00:11:46.120
Yes.
00:11:46.120 --> 00:11:47.400
Can you tell us about that?
00:11:47.400 --> 00:11:48.620
Yeah, sure.
00:11:48.620 --> 00:11:57.020
So this was a project we started because we wanted to get an overview of what problems you would find in Python code.
00:11:57.020 --> 00:12:11.460
And so we started collecting problem types and code smells and issues from different sources, for example, lintes like PyLint or PyFlakes that already have like a collection of a few hundred of those anti-patterns.
00:12:12.080 --> 00:12:20.620
But also from sources such as Stack Overflow and articles, blog posts, and also from people and from code that we were reading.
00:12:20.620 --> 00:12:28.760
And so we like collected all this together and then we worked with a freelancer in the beginning who helped us like write a large part of the initial text.
00:12:28.760 --> 00:12:40.420
And we bundled this whole collection of anti-patterns together into a book so that people could just like learn about different things they should avoid in their Python code.
00:12:40.420 --> 00:12:44.800
So it's not like learning from good code, but learning from bad code in this sense.
00:12:44.800 --> 00:12:45.660
Yeah.
00:12:45.660 --> 00:12:47.980
You know, it's related to that code smells idea.
00:12:47.980 --> 00:12:58.760
Like I see all these problems and if I know to avoid them, well, either you know the right design pattern and the right style or you just know you need to go do some research and don't do it this way.
00:12:58.760 --> 00:13:00.060
Yeah, exactly.
00:13:00.060 --> 00:13:00.400
Yeah.
00:13:00.400 --> 00:13:00.840
Yeah.
00:13:00.840 --> 00:13:06.100
In your book, you do have sort of recommendations for most of the anti-patterns, right?
00:13:06.100 --> 00:13:07.320
Yes.
00:13:07.840 --> 00:13:13.720
So we always, if we describe the problem, we always try to like give at least one or two solutions to it.
00:13:13.720 --> 00:13:24.060
I mean, sometimes there is no really unique solutions or people would kind of like disagree if it is a problem at all or not.
00:13:24.060 --> 00:13:31.040
So, but we are always pretty opinionated and we think like a good programmer should be a bit opinionated.
00:13:31.220 --> 00:13:35.900
And so we try to like give our solution that we would actually solve the problem with.
00:13:35.900 --> 00:13:37.140
Yeah, that's great.
00:13:37.140 --> 00:13:44.140
And let me just tell everybody that the book is at docs.quantifiedcode.com slash python dash code dash patterns.
00:13:44.140 --> 00:13:46.820
And of course, I'll put that in the show notes as well.
00:13:46.980 --> 00:13:47.740
Yes, that would be great.
00:13:47.740 --> 00:13:53.660
I mean, we also have like a GitHub repository and the whole book is open source released under a Creative Commons license.
00:13:53.660 --> 00:13:56.740
So we're always happy to see contributions.
00:13:56.740 --> 00:14:03.000
And like, yeah, so if people are interested, they would be very welcome to like contribute.
00:14:03.000 --> 00:14:04.520
Yeah, that's excellent.
00:14:04.520 --> 00:14:05.940
Let me pull this up here.
00:14:06.220 --> 00:14:11.340
So in your book, you've broken it into quick math, six sections.
00:14:11.340 --> 00:14:15.420
You have, you sort of categorize the problems that people run into.
00:14:15.420 --> 00:14:16.940
One of them is correctness.
00:14:16.940 --> 00:14:18.520
One is maintainability.
00:14:18.520 --> 00:14:21.900
Maintainability is one that catches up with you later.
00:14:21.900 --> 00:14:27.700
Readability, security, performance, and then you have a special section on Django.
00:14:27.700 --> 00:14:28.860
Yes.
00:14:28.860 --> 00:14:39.660
So yeah, I mean, as I said before, we tried to like just categorize the issues or anti-patterns so that people could like go through individual sections.
00:14:39.660 --> 00:14:50.440
And for example, see what type of problems really affect the correctness of their program and what type of anti-patterns only affect, for example, the readability or the performance.
00:14:50.440 --> 00:14:53.380
So let's maybe look at a couple of them.
00:14:53.380 --> 00:14:57.720
I'll just sort of scan through here and just tell people the kind of stuff that's in there.
00:14:57.720 --> 00:14:58.180
Sure.
00:14:58.800 --> 00:15:08.400
One that I think is somewhat common when you're new to programming in Python is this one you call bad accept clauses order.
00:15:08.400 --> 00:15:09.940
Can you talk about that?
00:15:09.940 --> 00:15:10.700
Yes.
00:15:10.700 --> 00:15:20.300
A bad accept clauses order basically means that you put an accept statement, that you have a sequence of multiple accept statements,
00:15:20.300 --> 00:15:27.520
where the first one of those statements is already more generic or general than the second one.
00:15:27.840 --> 00:15:31.040
So basically your second accept clause will never get executed.
00:15:31.040 --> 00:15:33.720
And that's kind of really easy to get wrong.
00:15:33.720 --> 00:15:36.880
It also happens to me a lot of the time.
00:15:36.880 --> 00:15:37.400
Yeah.
00:15:37.400 --> 00:15:37.440
Yeah.
00:15:37.440 --> 00:15:41.680
It's not obvious, especially if you're going back and adding these additional accept clauses.
00:15:41.680 --> 00:15:51.860
So maybe you say try, you're going to do some code and then you say accept exception as X and then accept type error as TE.
00:15:51.860 --> 00:15:52.540
Right?
00:15:52.540 --> 00:15:56.900
That type error will never get run because the exception is the base class of type error.
00:15:56.900 --> 00:16:02.880
Even worse than this, a pattern is probably an empty accept plug without also an exception type.
00:16:02.880 --> 00:16:06.200
I think that's kind of the most evil Python anti-pattern that exists.
00:16:06.200 --> 00:16:23.520
This episode is brought to you by CodeShip.
00:16:24.180 --> 00:16:32.380
CodeShip has launched organizations, create teams, set permissions for specific team members, and improve collaboration in your continuous delivery workflow.
00:16:32.380 --> 00:16:38.260
Maintain centralized control over your organization's projects and teams with CodeShip's new organizations plan.
00:16:38.260 --> 00:16:43.800
And as Talk Python listeners, you can save 20% off any premium plan for the next three months.
00:16:44.060 --> 00:16:47.320
Just use the code TALKPython, all caps, no spaces.
00:16:47.320 --> 00:16:53.040
Check them out at CodeShip.com and tell them thanks for supporting the show on Twitter where they're at CodeShip.
00:16:53.040 --> 00:17:07.240
I have to admit, sometimes I use it, but it's really bad because it swallows up all your exceptions and it doesn't give you any useful information about what happens in your code.
00:17:08.160 --> 00:17:15.020
Yeah, maybe if you're lucky, the empty accept clause at least has like a logging statement or something.
00:17:15.020 --> 00:17:15.740
Yeah, that's already good, yeah.
00:17:15.740 --> 00:17:20.880
Yeah, but if it has accept pass, that's pretty bad.
00:17:20.880 --> 00:17:21.900
That's really easy, yeah.
00:17:21.900 --> 00:17:24.920
I spend many hours debugging stuff like this, yeah.
00:17:24.920 --> 00:17:27.400
Most of the time I wrote that myself.
00:17:27.400 --> 00:17:32.520
Yeah, I like to think of that one as the intern clause.
00:17:32.520 --> 00:17:33.240
Yes.
00:17:33.240 --> 00:17:35.420
Because they're like, oh, this isn't working.
00:17:35.520 --> 00:17:38.540
Oh, I can just put this in here and my code is now reliable.
00:17:38.540 --> 00:17:40.140
I'll be out of here in three months.
00:17:40.140 --> 00:17:42.140
Let's see.
00:17:42.140 --> 00:17:44.100
There's some other interesting ones.
00:17:44.100 --> 00:17:49.220
Under future import is not the first non-doc string statement.
00:17:49.220 --> 00:17:50.820
What's the problem with that?
00:17:50.820 --> 00:18:02.760
Yeah, so this is just a convention of the Python interpreter because you can use these so-called future imports to import functionality that is usually not available in your Python version.
00:18:03.040 --> 00:18:05.900
For example, one thing that is often used are absolute imports.
00:18:05.900 --> 00:18:11.960
And the thing with the future imports is that they have to be the first statement in your file.
00:18:11.960 --> 00:18:19.420
So you cannot have auto code and then afterwards a future import because the Python interpreter needs to load these ones right at the beginning.
00:18:19.420 --> 00:18:26.420
So, I mean, this is kind of an easy pattern to catch, but still, sometimes it happens that you have this in your code.
00:18:26.880 --> 00:18:31.660
I mean, it's also something that you would notice really easily because your program wouldn't run even.
00:18:31.660 --> 00:18:32.700
Yeah, for sure.
00:18:32.700 --> 00:18:43.860
Another one that you can tell that people are coming from somewhere else and they haven't quite fully gotten the Pythonic idiomatic style is implementing Java style or C++ style getters and setters.
00:18:44.000 --> 00:18:44.240
Oh, yeah.
00:18:44.240 --> 00:18:45.320
Yeah, I like this one a lot.
00:18:45.320 --> 00:18:47.740
We also see it often in our analysis.
00:18:48.160 --> 00:18:56.040
And so this is basically when you write set something and get something function in a class, which you would do in Java.
00:18:56.040 --> 00:19:02.740
Whereas in Python, the appropriate or the correct way to do this would be to use so-called class properties.
00:19:02.740 --> 00:19:13.040
We can just have just access an attribute of a class using a function, which looks like an attribute access, so to say.
00:19:13.040 --> 00:19:13.820
Right.
00:19:13.820 --> 00:19:15.360
Just use the app property decorator.
00:19:15.360 --> 00:19:15.540
Yeah.
00:19:16.100 --> 00:19:16.820
Yes, exactly.
00:19:16.820 --> 00:19:17.260
Yeah.
00:19:17.260 --> 00:19:18.660
Yeah.
00:19:18.660 --> 00:19:21.320
Then there's others that are less obvious to me.
00:19:21.320 --> 00:19:25.560
One of them is if I'm using, I'm not using the default dict.
00:19:25.560 --> 00:19:27.080
What's the story of that one?
00:19:27.080 --> 00:19:29.800
Oh, so this is more a recommendation than a real antipodent.
00:19:30.340 --> 00:19:39.020
Python has this great collections library, which contains many data structures that can help you to make your code easier to understand.
00:19:39.020 --> 00:19:41.060
And the default dict is one of them.
00:19:41.060 --> 00:19:46.200
And it's one of my favorite ones and the one I probably use most in my code.
00:19:46.860 --> 00:19:56.120
And what it is, is a dictionary that basically initializes the value of a given key to something that you can pass in as a function.
00:19:56.120 --> 00:20:03.440
So the typical use case for this would be that you have a dictionary with a list inside.
00:20:03.800 --> 00:20:14.140
And so if you want to create an entry for some key that you haven't seen before, normally what you would need to do is to check if the key has been set in the dictionary before.
00:20:14.140 --> 00:20:18.000
And if not, create a list, an empty list in that place.
00:20:18.400 --> 00:20:20.180
And then append the element to the list.
00:20:20.180 --> 00:20:22.340
Yeah, so it's like three or four lines of code, right?
00:20:22.340 --> 00:20:25.660
But the default dictionary basically does, yes, so that's four lines of code.
00:20:25.660 --> 00:20:30.520
And the default dictionary basically does that for you because you can just say default dict of list.
00:20:30.520 --> 00:20:40.420
And then whenever you would like access a given value for a key in the dictionary, it will have created an empty list if there has been no value in it already.
00:20:40.420 --> 00:20:41.780
So really, really useful.
00:20:42.840 --> 00:20:50.100
And I did not know this when I started writing Python, but it really makes your code much more readable.
00:20:50.100 --> 00:20:50.700
Right.
00:20:50.700 --> 00:20:52.780
Does that come from the collections module?
00:20:52.780 --> 00:20:54.300
Default dict?
00:20:54.300 --> 00:20:55.240
Yes, exactly.
00:20:55.240 --> 00:20:55.680
Yeah.
00:20:55.680 --> 00:20:56.140
Yeah.
00:20:56.140 --> 00:20:56.440
Yeah.
00:20:56.440 --> 00:20:59.100
So it's not immediately imported, but it's easy to get to.
00:20:59.100 --> 00:21:00.360
Yes.
00:21:00.360 --> 00:21:01.700
It's in the standard library.
00:21:01.700 --> 00:21:02.020
Yeah.
00:21:02.020 --> 00:21:06.180
So another one that you have, let's move on to the next section of maintainability.
00:21:06.760 --> 00:21:13.780
And one of them I think is probably pretty common is you should not be using wildcard imports.
00:21:13.780 --> 00:21:16.440
So from math import star.
00:21:16.440 --> 00:21:19.040
It's so much easier to type.
00:21:19.040 --> 00:21:20.620
Why shouldn't I just do that all the time?
00:21:20.620 --> 00:21:21.220
Yeah.
00:21:21.220 --> 00:21:27.480
It's also a mistake which I made like a lot in the beginning when I started writing Python code.
00:21:27.480 --> 00:21:34.240
And it's pretty insidious because normally it doesn't break anything.
00:21:34.240 --> 00:21:39.480
But in some circumstances, you can overwrite functions that you have imported before.
00:21:39.480 --> 00:21:45.320
And so the behavior of your program changes in like really unexpected ways, I would say.
00:21:45.960 --> 00:21:50.480
And so today I always try to use only qualified imports.
00:21:50.480 --> 00:21:58.700
So either import the module and then use it as a name when I access the variable or explicitly name the things that I import from a module.
00:21:58.700 --> 00:21:59.180
Yeah.
00:21:59.180 --> 00:22:00.140
I'm with you on that.
00:22:00.140 --> 00:22:05.540
I try to, if it's not too much writing, try to use the name so it's really clear where the type is coming from.
00:22:05.540 --> 00:22:07.740
But sometimes, you know, it's like, well.
00:22:07.740 --> 00:22:08.860
Yeah.
00:22:08.860 --> 00:22:09.180
I know.
00:22:09.180 --> 00:22:10.160
I do it sometimes too.
00:22:10.160 --> 00:22:12.800
But, you know, more as like an explicit import.
00:22:12.800 --> 00:22:13.080
Yeah.
00:22:13.560 --> 00:22:17.940
So another area that you guys did a lot of work on was readability.
00:22:17.940 --> 00:22:26.160
And I think one of the ones that's, I don't know how easy this is for your system to check automatically.
00:22:26.160 --> 00:22:34.260
But certainly if you come from a language like Java or C# or C++ is not in your way of thinking.
00:22:34.260 --> 00:22:34.920
Right.
00:22:34.920 --> 00:22:38.140
Even though it's one of the core tenets of Python.
00:22:38.140 --> 00:22:40.880
And that's ask for permission instead of for forgiveness.
00:22:42.100 --> 00:22:45.740
Asking for permission is the anti-pattern rather than for forgiveness.
00:22:45.740 --> 00:22:46.260
Yes, exactly.
00:22:46.260 --> 00:22:46.640
Yeah.
00:22:46.640 --> 00:22:47.700
Can you tell people about that?
00:22:47.700 --> 00:22:59.740
So usually when you write Python code, the preferred way is to like assume that everything will go as you expect and not perform any checks.
00:22:59.740 --> 00:23:05.620
But rather catch an exception if some part of your program chose one.
00:23:05.620 --> 00:23:07.420
And like handle that exception.
00:23:07.420 --> 00:23:12.920
And then react to like behavior which you didn't anticipate, so to say.
00:23:12.920 --> 00:23:16.520
A good example is always like when you're opening a file.
00:23:16.860 --> 00:23:23.000
You could think of like checking if the path exists and then open the file at the path.
00:23:23.000 --> 00:23:29.980
But I mean between the two calls, like check of existence of the file and the opening, that could actually happen and stuff.
00:23:29.980 --> 00:23:35.180
And so your program could still crash and you will have an exception handler for that then.
00:23:35.560 --> 00:23:39.980
So the preferred way here is to just assume that the file is there and try to open it.