forked from mikeckennedy/talk-python-transcripts
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path025_effective_python.txt
1846 lines (923 loc) · 65.4 KB
/
025_effective_python.txt
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
00:00:00 What if you could bottle up all the wisdom and hard-fought experience of many expert Python developers and power up your skills?
00:00:05 That's what Brett Slatkin did, and he put it in his new book, Effective Python.
00:00:10 This is episode number 25 of Talk Python to Me, recorded Wednesday, August 12, 2015.
00:00:16 Welcome to Talk Python to Me, a weekly podcast on Python, the language, the library's,
00:00:46 the ecosystem, and the personalities.
00:00:48 This is your host, Michael Kennedy.
00:00:50 Follow me on Twitter, where I'm @mkennedy.
00:00:52 Keep up with the show and listen to past episodes at talkpython.fm.
00:00:56 And follow the show on Twitter via at Talk Python.
00:00:59 This episode is brought to you by Hired and CodeChip.
00:01:02 Thank them for supporting the show on Twitter via at Hired underscore HQ and at CodeChip.
00:01:07 It's another week with a book giveaway.
00:01:10 And just like last week's, this one is a really excellent one.
00:01:14 Make sure you're a friend of the show and you'll be in the running to win the free e-book version of Effective Python.
00:01:20 Just visit talkpython.fm, click on Friends of the Show, and boom, winning happens.
00:01:25 Well, sometimes, if you're lucky.
00:01:27 Now let me introduce Brett so we can get right to the show.
00:01:30 Brett Slatkin is the author of Effective Python.
00:01:33 He's the engineering lead and co-founder of Google Consumer Surveys.
00:01:37 He formerly worked on Google App Engine, the PubSub Hubbub protocol, and managing Google's fleet of servers.
00:01:44 Outside his day job, he works on open source tools and writes about software, bicycles, and other topics on his personal website.
00:01:50 And today, he lives in San Francisco.
00:01:53 Brett, welcome to the show.
00:01:55 Thanks for having me, Michael.
00:01:57 Yeah, I'm really excited to talk to you about your book and the other stuff you have going on with Python.
00:02:01 We're going to talk about this book that you recently released called Effective Python.
00:02:06 And I was a big fan of the Effective series back in the C++ days.
00:02:11 And so when I saw your book title, I was like, oh, this is going to be awesome.
00:02:14 So it's going to be a fun conversation.
00:02:17 Yeah, definitely.
00:02:17 And I similarly, Effective C++ was the best programming book that I ever had.
00:02:23 And so I totally agree with that.
00:02:27 So that was 1997 or 1998 when that came out when I first read it.
00:02:31 And being able to make the Python version of that was really a great honor for me to be able to write.
00:02:38 Yeah, I bet it was.
00:02:39 That's great.
00:02:40 Before we get into the details of your book, though, maybe we could just talk a bit about how you got to where you are.
00:02:47 How did you get into programming in Python?
00:02:49 Yeah, so I won't bore you with the super long details of my history of writing code.
00:02:55 But I've been writing code since I was about 10 or 11 years old.
00:02:58 My first job out of college was at Google.
00:03:02 And I showed up for my first day of work.
00:03:06 And they said, OK, here's this Python code base.
00:03:10 You need to make it better.
00:03:11 Here's a book.
00:03:12 And Alex Martelli sits right there.
00:03:15 Figure it out.
00:03:16 So I had seen Python.
00:03:18 I hadn't written any Python at all.
00:03:20 And I went from basically knowing nothing about Python and then actually writing a book about it in about 10 years, which is pretty funny.
00:03:28 Yeah, that's great.
00:03:29 The student becomes the master sort of thing, right?
00:03:32 Yeah.
00:03:32 I hope so.
00:03:33 I hope it's worthwhile.
00:03:34 Well, I think what was funny is that my first impression of Python was from the BitTorrent code base.
00:03:40 Because Bram Cohen had had this post all about Python and how it makes him more efficient.
00:03:44 And that's why BitTorrent's so awesome.
00:03:47 I don't think people realize that BitTorrent was written by Python.
00:03:50 But then like Zope and Plone, I thought were just really, they were code bases that I was very unhappy with using when I tried Python for the first time.
00:03:58 And that kind of turned me off.
00:03:59 So then when I showed up at Google and they said, OK, you're using Python, I was cautiously optimistic.
00:04:06 But it ended up turning out real well.
00:04:09 And so I can just go real quick, just the kind of projects that I used Python for at Google.
00:04:15 Yeah, people would love to hear that.
00:04:16 My first job there was kind of doing janitorial services for data centers.
00:04:23 Google has a bunch of machines in their data centers.
00:04:26 Those machines have a life cycle.
00:04:28 They're built.
00:04:28 They're repaired.
00:04:29 They break.
00:04:31 And I worked on a bunch of the tools to help that life cycle, which are primarily written in Python.
00:04:37 And I got to scale that out into Google's kind of worldwide network of data centers, a lot of system level code, a lot of networking, kind of database accessing, all kinds of stuff like that, workflows.
00:04:50 So that was my first kind of big role.
00:04:53 I did some other things similar to that around security and securing the machines in a data center.
00:05:01 And then shortly after that, that was a couple of years.
00:05:04 And then shortly after that, I heard of this really cool project that was being created called App Engine that had just started.
00:05:09 And I thought it really had a lot of potential.
00:05:14 And so I went and talked to that team.
00:05:16 I think it was four people at that point, the original founding team.
00:05:19 And I was like, what can I do to get on this team?
00:05:22 How can I work on this?
00:05:23 And in my 20% time, I built the App Engine Dev App Server, which is, I don't know if you've ever used App Engine, but you spend a lot of your time using this development tool to actually write your apps.
00:05:37 And so, yes, I built that.
00:05:38 And they're like, oh, this is pretty good.
00:05:39 And then they invited me to join the team.
00:05:41 And then I helped build App Engine out and launch it, which was, so it's, you know, platform as a service, Google's cloud kind of system.
00:05:49 Yeah, that's, it's really cool.
00:05:51 And was Python the very first language or was it Python and Go?
00:05:55 What was it?
00:05:56 It launched with just a restricted set, right?
00:05:58 Yeah.
00:05:58 So Python was the first language.
00:06:00 Java came like a year and a half or two years later.
00:06:02 And then, and then Go came a little bit after, like maybe two, two or three years after that.
00:06:09 I think the first language is actually supposed to be JavaScript, server-side JavaScript in the old Netscape, LiveScript scheme of things.
00:06:17 But in 2008, that seemed like a completely ridiculous proposition, which is pretty funny looking at all the Node.js stuff that's happened in the last few years with V8.
00:06:25 This is way before V8.
00:06:27 JavaScript is still really slow.
00:06:29 And so anyway, so they went with Python because it was one of the main languages that Google had used.
00:06:35 And Google had a lot of expertise in Python in general.
00:06:37 So on the App Engine team, I spent a lot of time working on Python infrastructure, Python APIs,
00:06:43 just kind of the feel of what it was like to write apps on top of App Engine using Python and fix a lot of bugs,
00:06:50 vetted new APIs to go out to make sure they felt good, built infrastructure around task queues and MapReduce and offline processing and all kinds of different things.
00:07:01 Did that for a few years.
00:07:04 And then also started this project called PubSubHubbub in there, which was a real-time RSS project for making RSS feeds real-time,
00:07:14 which is kind of hilarious also in hindsight now since that's pretty – it's kind of like saying I made something to design pogs or something like that.
00:07:22 It's kind of old.
00:07:23 Yeah, that's pretty funny.
00:07:25 But that was the Google Reader days and all that kind of stuff, right?
00:07:27 Yes, the good old days.
00:07:29 Yeah.
00:07:29 I kind of miss that thing still.
00:07:30 I do too, all the time.
00:07:33 I've been using News Blur recently, which I believe is also a Python app written in Django.
00:07:38 But, you know, anyway, I miss Reader.
00:07:40 Yeah, definitely.
00:07:42 So that is a bunch of really cool stuff.
00:07:44 And we might have to come back and talk about that at some later date in more detail.
00:07:49 That'd be really fun.
00:07:49 But let's talk about your book today.
00:07:51 It's called Effective Python.
00:07:53 What's the subtitle?
00:07:55 It's 59 Specific Ways to Write Better Python.
00:07:58 It's kind of based in this – the heritage of the Effective series, which, as we kind of hinted at the beginning,
00:08:04 I think that started out with Scott Myers and Effective C++, right?
00:08:08 Yeah, he invented the format.
00:08:10 And, you know, he's really the guy who came up with this way of educating people.
00:08:17 And all the other books are in his style.
00:08:20 Yeah, that's cool.
00:08:20 And so I remember when I was learning C++, I could sort of do stuff with it.
00:08:25 You know, I could write code and so on.
00:08:27 But after I read his book, I felt like it really took my understanding and effectiveness to a new level.
00:08:34 And so you're kind of trying to bring this to the Python developers, right?
00:08:37 Definitely.
00:08:39 Yeah, that's the goal of the book.
00:08:41 It's a bit of an audacious goal, but yeah.
00:08:44 Yeah, I mean, I think it's really simple is that, like, I read an introductory Python book.
00:08:49 This Effective Python is the book I would have given to myself as a second book if I had had the chance.
00:08:54 So there was a gap in my knowledge that took me years and years and years to fill.
00:08:59 And this book is kind of a way to shortcut and get all that practical knowledge without having to actually pay the dues.
00:09:05 So I wish I had had this book when I was starting out.
00:09:09 You know, we talk a lot about the concept of Pythonic code and idiomatic Python and stuff.
00:09:14 And there's a lot of that concept in there.
00:09:16 You know, like, this is the way you should do things in Python, even if you already know if you could accomplish it using your old idioms from, say, Java or C# or something.
00:09:26 But then there's another part, another angle to it that's just sort of broadening your horizon, I think.
00:09:35 So it's not just about writing Pythonic code.
00:09:37 And I'm thinking of things like how you would use, say, subprocess to manage child processes and parallelism from your Python app, right?
00:09:47 That's not technically a Pythonic thing, but it definitely ups your game and what you can do.
00:09:51 Yeah, I think, you know, a lot of the advice is pure language construct kind of stuff.
00:09:58 And then other things are like, yeah, the subprocess is item.
00:10:01 But, you know, it's important to remember that one thing that they say about Python is, you know, batteries are included, right?
00:10:06 And so, you know, the difference between Python as a language and Python as an ecosystem or Python as a set of libraries that you can use.
00:10:15 When people think of Python, they think of all of it together, both the syntax, the language features that it has, and then the libraries that you know you can rely on to always be there.
00:10:23 So those are tools you should have in your toolbox that are part of being a Python programmer, just like, you know, the collections API if you're a Java programmer, because it's basically all you write all the time.
00:10:34 Yeah, absolutely.
00:10:35 I have many friends that work in other languages, and they often want to compare their language to Python.
00:10:43 And like you said, I think that's not even a conversation you can begin to have if you don't think about the entire standard library and the 60,000 PyPI packages.
00:10:54 And, you know, you've got to take it as a whole, right?
00:10:56 It's not just, here's how you do properties here and properties there.
00:10:58 So this is either better or less good, right?
00:11:02 Yeah, totally.
00:11:02 I mean, a lot of these things, you have so much, I like to use the word leverage, you know, to describe, you get to stand on the shoulders of giants.
00:11:10 There's a lot of different ways to say it.
00:11:11 But yeah, things like NumPy, as an example of a library, it's a whole ecosystem unto itself.
00:11:17 And trying to do the equivalent in Java or C++ is extremely difficult.
00:11:22 Yeah, that's for sure.
00:11:24 So I thought one way that would be fun to have a conversation about your book is kind of go from section to section or chapter to chapter and pick out a few interesting pieces of guidance from each one of them.
00:11:36 Yeah, definitely.
00:11:37 Yeah, cool.
00:11:38 So you broke your book into six parts, and we'll just take them one at a time.
00:11:42 So the first one is this concept of sort of the libraries and Pythonic thinking, right?
00:11:48 Yeah, that's the first part.
00:11:49 It's actually eight separate chapters is how many there are, because it keeps going.
00:11:53 But yeah, the first one is Pythonic thinking.
00:11:58 Excellent.
00:11:59 So why'd you start with that?
00:12:01 Yeah, I think that it's kind of like the strange universe of Python syntax.
00:12:07 You have to get used to doing things.
00:12:09 Even simple expressions like, I remember when I first started writing Python, and the not operator, as opposed to using the bang or exclamation point, getting used to where that not goes.
00:12:19 And things like is not, as opposed to, you could do A is not B, or you could do not A is B.
00:12:26 And, you know, understanding that the Pythonic way is A is not B. That's how you'd say it.
00:12:30 So you really need this base to start with, so that all the other things make sense or are in context.
00:12:37 Right. I also think it's probably a good way to kind of shock the system a little bit to prepare them for, like, this is a different world, probably, than you're coming from.
00:12:45 Yeah.
00:12:46 And so get prepared to think differently.
00:12:48 Yeah, it's to open, I think it's a good way to say it, because I think it's, if you try to fit it into the way you're writing other languages, you're going to have a bad time.
00:12:56 And you really need to embrace the Pythonic way of doing it.
00:13:00 I had one person told me once that my C++ code looks like Python.
00:13:04 I thought that was a really great compliment, I guess.
00:13:08 But you don't really want your Python to look like C++, right?
00:13:10 Yeah.
00:13:11 Absolutely.
00:13:12 Cool.
00:13:13 So the very first thing that you talk about, literally the first piece of guidance, is to know what version of Python you're using.
00:13:21 And I do a lot of training in Python, and it's always a problem.
00:13:25 Someone's always running the wrong version of Python, or even worse, they're trying to use a package and they install it into the wrong version of Python,
00:13:33 and then they're running the right one or something like that, right?
00:13:35 Yeah, that's a big problem, especially with the Python 3 move that's going on.
00:13:39 You know, you can get confused really easily.
00:13:41 And then a lot of the features that people like to use, like even with statements, are actually more recent developments.
00:13:46 So if you're on some old version, some versions of macOS are like running Python 2.5, and you don't know it,
00:13:52 and you try to do simple things like a with statement, it doesn't work.
00:13:54 And so that can be very surprising.
00:13:57 So it's always good to check your assumptions.
00:13:58 Yeah, absolutely.
00:13:59 So sort of level set, all right, we all know what we're talking about.
00:14:02 Now we can move forward, right?
00:14:03 Yeah, exactly.
00:14:05 So what I think probably a lot of people are familiar with, but some are not, is sort of working with sequences.
00:14:12 And you say you should prefer using list comprehensions over like chaining a map and a filter call together.
00:14:18 Yeah.
00:14:21 Yeah, so I think if you, yeah, I think the story, so it's interesting, because if you look at the history of Python, people will talk about how, oh, I like Python, because it's kind of functional, but it's kind of object oriented, and it's kind of scripty.
00:14:33 And so you'll still see examples or guides today.
00:14:36 You'll be searching around the internet, and you'll find some old guide on active state from like 2006.
00:14:40 And it's like, here's how you should use map and filter.
00:14:42 And, or even 2003, like, you know, a long time ago.
00:14:47 And those are useful tools, sometimes they're useful, but the list comprehension syntax is just so much more pithy.
00:14:54 I think that Python over the years has added more and more tools to maximize the readability of code, and to minimize the visual noise, the extra parentheses and brackets and various symbols that you need to express something.
00:15:07 And so I think that map and filter are kind of just antiquated tools that are in the language, because they're hard to take out, because they're, you know, kind of keywords, built in functions.
00:15:18 If I had my way, I would just take them out, because I think list comprehensions are better.
00:15:22 This episode is brought to you by Hired.
00:15:36 Hired is a two-sided, curated marketplace that connects the world's knowledge workers to the best opportunities.
00:15:42 Each offer you receive has salary and equity presented right up front, and you can view the offers to accept or reject them before you even talk to the company.
00:15:52 Typically, candidates receive five or more offers in just the first week, and there are no obligations, ever.
00:15:58 Sounds pretty awesome, doesn't it?
00:16:00 Well, did I mention there's a signing bonus?
00:16:02 Everyone who accepts a job from Hired gets a $2,000 signing bonus.
00:16:06 And as Talk Python listeners, it gets way sweeter.
00:16:10 Use the link Hired.com slash Talk Python To Me, and Hired will double the signing bonus to $4,000.
00:16:19 Opportunity's knocking.
00:16:20 Visit Hired.com slash Talk Python To Me and answer the call.
00:16:34 But yeah, the main thing is that, you know, if you have two ways of doing something, I think the Pythonic way of doing it is always the more clear and more explicit and obvious way of doing it.
00:16:45 And so yeah, so that's why I think list comprehensions are definitely the way to go.
00:16:48 Yeah, that's cool.
00:16:50 I totally agree.
00:16:51 It's not exactly a more declarative way of programming, but it's closer, right?
00:16:56 That's nice.
00:16:57 Yeah, it's more obvious.
00:16:58 Sort of related to that, one of your other pieces of guidance was that you should use generators for large list comprehensions.
00:17:05 Yeah.
00:17:06 It's so easy to switch from one to the other, but when should I use one?
00:17:09 When shouldn't I?
00:17:10 What's the story of that?
00:17:11 Yeah, so I think that, you know, Python can use a lot of memory is one big thing.
00:17:16 And depending on what you're trying to do, if you're dealing with a small data set that entirely fits within memory, then you don't have to really think about this.
00:17:24 You can just read everything as a list and just work on lists.
00:17:27 So if you're reading a file, like a CSV file, and you want to deal with it line by line or something like that, then reading the whole thing into memory is fine.
00:17:35 But what always happens is you end up wanting to do something a little bit bigger than you expected, especially with a lot of the data processing stuff that people are doing in Python these days.
00:17:44 And so I'm trying to change the culture a little bit to say, hey, why not use a generator if you can?
00:17:52 Because if you use a generator, then all of these memory problems go away.
00:17:57 A generator returns one item at a time.
00:17:59 It doesn't fully materialize the list.
00:18:01 So the total memory space that's occupied is just the last thing you return from the generator.
00:18:07 The rest of it gets cleaned up, garbage collected.
00:18:10 Yeah, that's fantastic.
00:18:11 Especially if you're like chaining one to another to another, and they're kind of building up.
00:18:17 It's really efficient.
00:18:19 Yeah, and to that point, I mean, I think that if you start by at the base level, like if you want to switch to generator code, it's difficult because you have to, you have to,
00:18:27 put generators all the way down to the leaves of your call stacks.
00:18:30 But if you start with generators at the leaves, then it's very easy to start saying, hey, you know, I'm going to turn this into a streaming generator.
00:18:35 And so creating those cascades of generators becomes very straightforward.
00:18:39 And so you can get quick, you know, very fast executing code that's easy to follow and uses a low amount of memory very, you know, very cheaply.
00:18:48 And it's very readable.
00:18:50 So that's why I suggest that.
00:18:53 So the final language one that I wanted to sort of point out is something that I always thought was weird is the whole concept of the else statement on a loop.
00:19:04 Yeah.
00:19:05 And something I recently learned is that try except finally also supports else.
00:19:12 It does.
00:19:13 Yeah.
00:19:13 Yeah.
00:19:14 And you have really interesting guidance.
00:19:15 You say, you know what, these, this else statement on loops, maybe not so much, but on exception handling, it's very cool.
00:19:20 It's like an alternative to the catch.
00:19:22 Yeah, definitely.
00:19:23 Yeah.
00:19:24 So I think else, else makes a lot of sense for try except finally, because you're basically saying, you know, try to do this.
00:19:31 If an exception happens, do this.
00:19:33 And if no exception happens, then do this other thing.
00:19:36 And that's what the else block is on a, on an exception, kind of try except.
00:19:40 and so that makes things really clear, clearly delineated what will and will not happen inside your exception handling.
00:19:45 and when you're doing exception handling, you want the, the try block to be as small as possible to narrow what you're catching.
00:19:52 So that, that exceptions you didn't plan to catch are raised back up.
00:19:56 That's, that's like a really important thing.
00:19:57 Yeah, that makes sense.
00:19:58 And the other thing is, you know, you might think, well, just the last bit of code in your try bit, your try try block could be what would go in the else statement, but that doesn't account for like early returns.
00:20:11 And so, you know, if you were to do, try to do some stuff, if this, oh, just return, it would still run that else, but then you'd have to be really careful, you know, trying to put that cleanup all over the try.
00:20:22 So yeah, it's really nice.
00:20:23 Yeah, it's nice.
00:20:24 And yeah, you can put like final cleanup stuff in the finally, and that'll always run if you have an early return.
00:20:29 And if you have an else with an early return, that'll also still run the finally.
00:20:32 So it's, it's super nice.
00:20:34 Going to that back to that for loop part of it.
00:20:36 Yeah, I think that's one of the big things.
00:20:37 Like when people first learn about that in Python, they're like, oh, this is so great.
00:20:40 I can, I can use it for doing this and that.
00:20:43 And it's, there's really, yeah, I think it's something to avoid.
00:20:47 It's kind of like, it's a shiny new toy and you want to use all the different parts of it for you, you know, and you have to like stab yourself in the eye before you realize that you're getting, that wasn't a good idea.
00:20:57 That thing hurts.
00:20:58 Yeah, it hurts.
00:20:58 Like, oh, it's short.
00:20:59 It's pointy.
00:21:00 I shouldn't touch that.
00:21:00 And I was talking to, I was talking to Guido about this one in particular because he said, you know, cause I was asking him what he thinks about this one.
00:21:10 Cause it's kind of, it's kind of tough.
00:21:12 I had worked with Guido on App Engine for a few years and, so, and I see him at PyCon from time to time.
00:21:17 And so, you know, I felt bad by saying like, hey, you shouldn't use this part of the language.
00:21:20 I just, you know, wanted to make sure it wasn't ridiculous to him.
00:21:23 And, you know, he said that it's actually an implementation detail of how the Python, the CPython runtime is implemented.
00:21:29 the way that the for else block, the else with loops works has to do with the way these go to statements actually work in the Python interpreter.
00:21:37 and so if you, if you, if you wrote that code, then it makes perfect sense because the else has to do with the way the certain switch or go to statement works.
00:21:47 it's switch statements.
00:21:48 Sorry.
00:21:48 It's not a go to thing.
00:21:49 It's a switch.
00:21:49 And, but if you don't have that mental model, then it makes no sense.
00:21:53 And, you know, I think that, so for, for Guido and maybe other people who've hacked on the core, they just get it and it makes sense to them, but everyone else they have, it does the opposite of what you would expect.
00:22:04 And so just because of that, I think it's too sharp and I think it's something you should avoid.
00:22:08 Talk Python To Me is partially supported by our training courses.
00:22:13 Do you want to learn Python, but you can't bear to subscribe to yet another service at Talk Python Training?
00:22:19 We hate subscriptions too.
00:22:20 We hate subscriptions too.
00:22:21 That's why our course bundle gives you full access to the entire library of courses for one fair price.
00:22:26 That's right.
00:22:27 With the course bundle, you save 70% off the full price of our courses and you own them all forever.
00:22:33 That includes courses published at the time of the purchase, as well as courses released within about a year of the bundle.
00:22:40 So stop subscribing and start learning at talkpython.fm/everything.
00:22:46 All right.
00:22:47 So the next chapter was functions and there's a lot of good stuff in there.
00:22:50 One of them that I'm a fan of is the whole sort of concept of it's easier to ask for forgiveness than permission.
00:22:57 Okay.
00:22:59 And, you know, that sort of manifests in your recommendation of saying prefer exceptions rather than returning none from functions.
00:23:05 Yeah.
00:23:06 Yeah, definitely.
00:23:06 Yeah, this one I think that people, they're always looking, I don't know if you've ever heard of like a tribool.
00:23:13 There's always this joke about a tribool.
00:23:15 It's a Boolean value of three, you know, values, tribool.
00:23:18 People are always dying for a tribool because it's, you know, it's true or it's false or it's some exceptional case that's neither true or false.
00:23:24 And none in Python ends up playing that role a lot of the time.
00:23:28 And that's a problem because in Python, both false and none evaluate false.
00:23:37 They're falsy values.
00:23:38 And so what ends up happening is it introduces a lot of bugs into your code because you say, hey, you know, x equals this function call.
00:23:45 And then if x, then do this other thing.
00:23:48 Or if not x, do this, then there's an error.
00:23:51 But if you're returning none, then that if not x kind of statement is going to run no matter what.
00:23:59 And so my whole point, I've been hit by this bug in production a whole bunch of times.
00:24:03 I had to learn this one the hard way over the course of many years.
00:24:07 And I'm still managing a code base that has a bunch of this in it and trying to take it out.
00:24:13 And so my advice here is if you have anything exceptional, just always raise an exception.
00:24:16 That's what exceptions are for.
00:24:18 I think people coming from other languages are used to exceptions costing a lot of CPU time or somehow, you know, cause a lot of cache problems.
00:24:28 And that's true for C++ and other languages.
00:24:31 But in Python, raising exception is a little bit of cost to it, but it's not enough to matter.
00:24:36 And the clarity is worth it.
00:24:38 Not enough to introduce bugs into your code, right?
00:24:41 Yeah, exactly.
00:24:42 It's like, okay, well, it's fast, but it doesn't work correctly.
00:24:44 It's like, all right, well, if that's what you want, then that's fine.
00:24:46 Yeah, that's not a trade-off you want to make, right?
00:24:49 Yeah, not the right trade-off.
00:24:50 Sure.
00:24:51 So another one you had around functions that I thought was good advice was if you're going to return a lot of data, just make that function a generator rather than returning a list.
00:24:59 Yeah, and this kind of goes hand in hand with, you know, generator statements that I was talking about before.
00:25:08 I think I kind of covered both of those when I was talking before.
00:25:10 So, you know, generator expressions, there's list comprehensions, which, you know, are a fastest way of doing map and filter on lists.
00:25:17 Then there's generator expressions, which is a way of doing exactly the same thing, but the data is generated one at a time.
00:25:22 And then a generator function is just a, it's not just a one-liner, it's like a full function that does this.
00:25:28 And that's, so what I was talking about before, I think I kind of conflated both of those together.
00:25:32 Yeah, I think just having functions that return, that are generators, like I was saying, lets you kind of start with the leaves and move up to make things streaming.
00:25:39 Yeah, and it's so easy to just throw in a yield, you know, instead of list.append or whatever, right?
00:25:47 Yeah, exactly.
00:25:47 It's very clear.
00:25:48 And what's interesting is that, you know, JavaScript and other languages are adopting the yield semantics because it's such a powerful tool that people love to use, which is really great.
00:25:58 And I'm sure Python stole it from something else.
00:25:59 I actually don't know exactly where it yields from originally, but it's a really great tool.
00:26:03 Yeah, it's really great.
00:26:05 And it's one of those that I find that a lot of people, they haven't taken the time to really learn it and appreciate it.
00:26:12 They know it's there and then they just kind of ignore it, right?
00:26:15 But knowing, sort of raising the awareness is great.
00:26:18 Yeah, definitely.
00:26:19 And it should be the default.
00:26:21 I think you should just always, you should like plan to yield.
00:26:24 Plan, like if you're returning and it's not, if you're returning a sequence, like question what you're doing.
00:26:29 Yeah, exactly.
00:26:31 The thing better be pretty short.
00:26:33 So the last one I want to talk about in functions, which I haven't necessarily decided my feelings on it yet, but is if you use keyword arguments, that can help in the expressivity and clarity of functions.
00:26:47 Yes.
00:26:48 So I think the actual recommendation was to use just keyword arguments if you get a chance sometimes, right?
00:26:55 Go ahead.
00:26:56 Yeah.
00:26:56 Maybe speak to that a bit.
00:26:57 Sure.
00:26:57 So, well, I was curious what part you don't necessarily agree with because I'm curious.
00:27:02 So, yeah, I mean, because I have a few different parts to my advice, but yeah, keyword arguments are extremely powerful.
00:27:08 They let you be explicit about your intention.
00:27:13 And yeah, I think that using them in general for optional parameters is really important.
00:27:21 So if you have a function that takes an optional flag, then you should always use, you know, keyword argument is a great way to do that.
00:27:26 No, I was going to say that I totally agree with.
00:27:28 I think where there's an optional thing, it definitely helps because it's not part of what you expect to pass all the time.
00:27:36 Right.
00:27:36 Yeah, because Python doesn't have polymorphism like other languages.
00:27:39 So in Java, you can define the same function name that takes three different sets of parameters.
00:27:43 You know, C++ can do that too.
00:27:44 And in Python, you can't do that.
00:27:46 So the only way to deal with this is to basically add additional optional parameters to one function and have it kind of deal with the various types of input or define a totally different function of the different name, which can get verbose.
00:27:57 Right.
00:27:59 Yeah, I'm not sure I disagree with you.
00:28:01 I just haven't fully internalized that one yet.
00:28:03 Yeah.
00:28:03 So the use case that I was thinking of is if you have some kind of rich IDE, something like PyCharm or Python tools for Visual Studio or something, and you hit open parenthesis and there's like a nice listing of all the parameters without even looking at the docs, which for optionals, I think that still does show up.
00:28:20 But if you just do like the star star KWRs.
00:28:23 Oh, yeah.
00:28:23 Then you got a problem.
00:28:24 Then it's really like, okay, what the heck can I pass?
00:28:28 Yeah, no, that's totally true.
00:28:29 So star star KWRs, which basically is a catch all.
00:28:33 It's you catch any keyword arguments no matter what they are, including garbage.
00:28:36 It can be a problem.
00:28:37 And this is one of the things that I've tried really hard in the book to do, which is I provide advice that applies both to Python 2 and 3.
00:28:46 So it's not a Python 2 book.
00:28:48 It's not a Python 3 book.
00:28:49 It's like the most overlapping subset that I could find of both.
00:28:52 So it should be relevant to everyone.
00:28:55 And this is a great example.
00:28:56 Python 3 has specific language features that would make it so your IDE will continue to work properly, whereas Python 2 does not.
00:29:04 So in Python 2, you can't say these arguments can only be passed by keyword.
00:29:10 And you want to do that in situations where you're passing two integer values and you don't know which is which.
00:29:16 And so you want to use the keyword part in the function call to make it really clear that, like, hey, this is the numerator and this is the denominator.
00:29:23 And it's not the other way around.
00:29:24 So here's a label in the function call.
00:29:28 Numerator equals 5 and denominator equals 10 or something like that.
00:29:32 And you want to enforce that behavior so that people can't call it by just passing 5 and 10 or 10 and 5 on accident.
00:29:37 And so in Python 3, you can just add this star into the arguments list and then that's enforced by the compiler and everything's great.
00:29:46 And in Python 2, you can't do that.
00:29:47 So that star star kwrks is a way to deal with that.
00:29:50 And you're right.
00:29:51 It breaks your IDE.
00:29:52 It makes it harder to understand the documentation.
00:29:54 You have to make that tradeoff for you and say, hey, how error-prone is this function?
00:29:58 Is it worth doing this, you know, having these optional parameters that are in this way?
00:30:04 And, yeah, maybe there's a better design that you could have, maybe a helper class that would be a better way to approach it than having kwrks, star star kwrks, sitting there.
00:30:11 Right.
00:30:12 It's definitely a cool language feature.
00:30:13 It's just I think sometimes it gets overused and you're like, okay, I've got to basically keep the documentation up for a while so I know what my possibilities are, you know?
00:30:21 You're totally right.
00:30:22 I would say don't use star star kwrks unless you're doing something like this.
00:30:27 I think it's one of the few times you should use it.
00:30:30 There's some other glue kind of infrastructure times that are good to use it if you're doing, like, generic wrappers of functions and stuff like that.
00:30:36 But in general, I try to stay away from it.
00:30:38 And I'm really happy that Python 3 has this extra forcing keyword arcs feature.
00:30:43 Yeah, that's cool.
00:30:44 Okay, then I definitely agree with you.
00:30:46 Okay.
00:30:47 Thanks.
00:30:47 This episode is brought to you by Codeship.
00:31:05 Codeship has launched organizations, create teams, set permissions for specific team members, and improve collaboration in your continuous delivery workflow.
00:31:14 Maintain centralized control over your organization's projects and teams with Codeship's new organizations plan.
00:31:19 And as Talk Python listeners, you can save 20% off any premium plan for the next three months.
00:31:25 Just use the code TALKPYTHON, all caps, no spaces.
00:31:28 Check them out at Codeship.com and tell them thanks for supporting the show on Twitter where they're at Codeship.
00:31:40 So let's move on to classes.
00:31:41 One thing that Python supports is multiple inheritance.
00:31:46 And speaking about, oh, that's sharp, that hurts, is I did a lot of C++ and even COM with insane templating, multiple inheritance.
00:31:56 And I just, I kind of prefer single inheritance and just keep it really simple.
00:32:03 And so you were, you're saying that to some degree and you're saying, look, this multiple inheritance stuff should be used for mix-ins.
00:32:09 Yeah, definitely.
00:32:10 Yeah.
00:32:11 So I.
00:32:11 Can you tell people what you mean by mix-ins in this case and like how that would go?
00:32:15 Yeah.
00:32:16 So I think that a mix-in to me is, is a set of functionality that you can add to a class.
00:32:22 You can add to any class.
00:32:23 So helpers for serialization, helpers for logging, helpers for, you know, doing some kind of introspection on functions and stuff like that.
00:32:34 Those are the mix-ins where you're like, hey, I have this class.
00:32:37 Wouldn't it be nice if it automatically logged every function call or something like that?
00:32:40 Or every attribute access.
00:32:41 Let me, let me, let me inherit from this mix-in utility to do that for me.
00:32:45 So I think that those are the times where you want to use multiple inheritance, where the class structure doesn't actually matter.
00:32:52 It's more like aspect-oriented programming or something like that, where, which I'm not necessarily a huge fan of, but I'm just trying to say that it's nice to be able to kind of compose functionality.
00:32:59 And so mix-ins are a way of doing composition with class inheritance.
00:33:05 If there were another way to express that composition in Python, that'd be great.
00:33:09 But the tool that we have is, is multiple inheritance.
00:33:12 Yeah.
00:33:13 And I have seen some really beautiful mixing code that, that when done right, right, is nice.
00:33:18 Yeah.
00:33:19 When it's done correctly, it's, it's really, really nice.
00:33:21 And, and it doesn't, it's not brittle.
00:33:24 I think a lot of the time, multiple inheritance is, is really brittle and it breaks in weird ways when you refactor it.
00:33:29 And mix-ins are built not to be brittle.
00:33:32 And so that's why it works out.
00:33:33 So it's about composition, primarily.
00:33:36 Nice.
00:33:37 So let's move on to the next section, meta classes.
00:33:40 Yeah.
00:33:41 And in there, one thing that was sort of stood out to me was you're talking about that you can register class existence with the meta class.
00:33:49 What's the story of that?
00:33:51 Yeah.
00:33:52 So, you know, meta classes are like the sharpest tool you can poke yourself with in Python.
00:33:57 And it's kind of like, once you use it enough, Python enough, you're like, okay, I'm going to try out these meta classes thing.
00:34:02 And maybe you read Eric Raymond's thing about meta classes and some email filtering thing he wrote with them and how awesome that was.