forked from mikeckennedy/talk-python-transcripts
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path024_fluent_python.txt
1818 lines (909 loc) · 66.7 KB
/
024_fluent_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 Are you fluent in Python, or do you speak the language with an accent?
00:00:03 Python's ease of learning can also lead to non-Pythonic patterns for even experienced developers.
00:00:08 Luciano Romalo is here to give us a deeper understanding of this language we love.
00:00:12 It's episode number 24, recorded Thursday, August 6, 2015.
00:00:17 I'm a developer in many senses of the word, because I make these applications, but I also use these verbs to make this music.
00:00:28 I construct it line by line, just like when I'm coding another software design.
00:00:33 In both cases, it's about design patterns. Anyone can get the job done, it's the execution that matters.
00:00:39 I have many interests, sometimes conflict.
00:00:42 Welcome to Talk Python to Me, a weekly podcast on Python.
00:00:46 The language, the libraries, the ecosystem, and the personalities.
00:00:49 This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy.
00:00:53 Keep up with the show and listen to past episodes at talkpython.fm.
00:00:57 And follow the show on Twitter via at Talk Python.
00:01:00 This episode is brought to you by Hired and CodeChip.
00:01:03 Thank them for supporting the show on Twitter via at Hired underscore HQ and at CodeChip.
00:01:09 Before we get to the conversation with Luciano, he generously agreed to give away an electronic copy of his book, Fluent Python.
00:01:15 All you have to do to be eligible to win is to be a friend of the show.
00:01:19 Visit talkpython.fm, choose friend of the show in the nav bar, and sign up.
00:01:24 Now, let me introduce Luciano.
00:01:25 Luciano Romalo is the author of Fluent Python.
00:01:28 Romalo was a web developer before the Netscape IPO in 1995 and switched from Perl to Java and finally to Python in 1998.
00:01:36 Since then, he's worked on some of the largest news portals in Brazil using Python.
00:01:40 He's taught Python web development in the Brazilian media, banking, and government sectors.
00:01:45 He's spoken multiple times at OSCON, PyCon, Python Brazil, FISL, and Rupy.
00:01:50 Romalo is a fellow at the Python Software Foundation and a co-founder at the Garoa Hacker Club, the first hackerspace in Brazil.
00:01:58 Finally, he's the managing partner at python.pro.br at Python Training Company.
00:02:03 Luciano, welcome to the show.
00:02:06 Thanks, Mike.
00:02:06 Thanks for having me.
00:02:07 Yeah, I'm really excited to talk to you about your new book, Fluent Python.
00:02:11 Yeah, I'm excited about it too.
00:02:13 I bet.
00:02:14 You've been working on it for a while.
00:02:16 Before we get into talking about your book, which is really an amazing book, I'll have more to say on that in a minute.
00:02:21 Thanks.
00:02:22 You're welcome.
00:02:23 Let's talk about how you got started in the programming and Python at all.
00:02:27 You know so much.
00:02:29 I can tell from your book.
00:02:30 But at some point, you had to start at the beginning, like we all do, right?
00:02:34 Where did you get started?
00:02:36 Okay.
00:02:36 Now, I'm 51 years old.
00:02:39 So when I was a teenager in Brazil, there were no microcomputers.
00:02:44 But I got a hand on a programmable calculator, a TA-58.
00:02:51 And I learned to program by programming it.
00:02:54 And actually, my first interesting program was a port of a game from the HP-25 calculator to the TI-59.
00:03:02 It was the lunar landing game that was famous.
00:03:06 Oh, that was a great game.
00:03:07 Yeah.
00:03:08 So that was my first significant program.
00:03:12 And then I was an exchange student in 81 in the US.
00:03:16 I lived in Little Harrisburg, Illinois, population 10,000.
00:03:21 And there I got – there were – in the library, in the school, there were a few Apple II computers that had just arrived when I arrived.
00:03:31 And nobody knew how to use them.
00:03:33 The teachers who were supposed to teach about them hadn't yet taken the course to do it.
00:03:40 So they were basically free for anyone to do whatever they wanted.
00:03:43 And I learned – I taught myself basic programming in them.
00:03:48 Anyway, so that's a long time.
00:03:50 And then I went through lots of languages after basic, Pascal.
00:03:54 And Pascal was one of the most important ones for me.
00:03:58 And then Delphi.
00:04:00 And then Visual Basic.
00:04:02 And I studied a little bit of small talk.
00:04:07 And then when the web started here in Brazil, again, we had a kind of a different situation because there was – all telecom companies in Brazil were state-owned at that time.
00:04:19 Later they were privatized, but they were state-owned in 94.
00:04:24 And so I was hired by a large publishing company here to start developing their strategy for online.
00:04:30 And I learned – I taught myself pro programming because everybody did everything on the web that was automated using Perl at the time.
00:04:37 Right?
00:04:38 Right.
00:04:39 And I loved Perl.
00:04:41 I thought it was awesome.
00:04:42 But I also found it – well, I'm saying I just said I love it.
00:04:48 But I loved it, but I also hated it at the same time because it was very powerful and quick.
00:04:53 But it was also full of traps.
00:04:56 And it was difficult to read afterwards and so on.
00:05:01 Then I tried Java and I probably was one of the first people in Brazil to do server-side Java because when Java was first released, Sun was trying to market it as a tool for client-side programming, right, with the applets and so on.
00:05:18 It took a while for them to realize that server-side was where Java was going to thrive.
00:05:24 But I didn't enjoy the verbosity of Java.
00:05:27 I liked the fact that it was really object-oriented, which Perl was not at the time.
00:05:32 But it was too verbose.
00:05:34 And then after a while, I went back to Perl again.
00:05:37 And Perl had acquired object-oriented features in around Perl 5.
00:05:43 And then something happened.
00:05:45 As the Perl community was discussing how to do things in a dynamic language, but also in an object-oriented way,
00:05:54 they kept repeating the sentence.
00:05:58 Here's how they do it in Python.
00:06:00 In Python, this is like that.
00:06:03 And that's how I first heard of Python.
00:06:05 It was discussions on the Perl mailing list about how to do things in an object-oriented way,
00:06:13 but in a language that was a scripting language, in a dynamic language.
00:06:16 So after reading mentions of Python a few times, I decided to go study it.
00:06:20 And then I read the tutorial, which was shorter at the time than it is now.
00:06:25 And I just fell in love immediately because for me, it had the best features of Python, of Java and Perl.
00:06:35 It was really object-oriented with an object-oriented standard library like Java and had exceptions and other things that I liked about Java,
00:06:47 but was not verbose.
00:06:49 So it was, you know, very concise and to the point and agile like Perl.
00:06:57 And so it was for me the combination of the best features of both languages.
00:07:02 And then I basically never looked back.
00:07:04 That's a great story.
00:07:06 I think we've all had those sorts of feelings about some of our first programming languages.
00:07:12 We love them because we really got into programming, but, you know, they're not necessarily the best.
00:07:17 So you have those words as well, right?
00:07:19 Exactly.
00:07:20 But Python's where you've sort of settled into.
00:07:24 I can tell you've been doing it for a long time from your book.
00:07:26 Yeah.
00:07:28 So I started doing it in 98.
00:07:30 That was when I found the tutorial that I mentioned.
00:07:33 And then I immediately pitched a Python solution to a client at the time for an online news site.
00:07:43 And then I discovered Zope, which was just then released as open source.
00:07:51 And I started using it like a couple weeks after it was released as open source.
00:07:58 And then a couple months later, we actually launched in Brazil a new site that was based on Zope.
00:08:05 And it was one of the first big Zope cases around the world.
00:08:09 Oh, that's excellent.
00:08:11 Yeah.
00:08:11 And so I owe a lot to Zope.
00:08:13 I don't use Zope anymore these days, but I owe a lot to it because it was because of Zope that I was able to deliver the kinds of products that the clients were looking for me to deliver, like content management systems.
00:08:29 And so I was able to get paid for writing Python pretty early, at least in the context of Brazil, since 98.
00:08:39 That's a great feeling, right?
00:08:40 Yeah.
00:08:41 You find this thing you love and, wow, people pay me to do it.
00:08:43 Exactly.
00:08:44 Exactly.
00:08:45 It's a good time to be a programmer indeed.
00:08:47 So let's talk a little bit about your book.
00:08:49 The title is Fluent Python.
00:08:51 And it's coming out under, being published by O'Reilly.
00:08:54 And it's coming out, I think, September 4th is what Amazon.com tells me anyway.
00:08:58 Is that right?
00:09:00 Yeah.
00:09:00 To be honest, I don't know exactly when the print book is going to come out because different pages that I look at give different dates.
00:09:06 I've seen August.
00:09:07 I've seen September.
00:09:08 And I've seen October all in the last two weeks.
00:09:11 So, yeah.
00:09:14 But soon, right?
00:09:15 Pretty soon.
00:09:16 Just about the same time that this podcast comes out, I think, should be the time that the book is released.
00:09:20 Wow.
00:09:21 That's excellent.
00:09:22 But let me say, the e-book is now complete in the final form.
00:09:29 So people who buy the e-book or who have bought it previously can now download the final version of, you know, first edition, first revision.
00:09:40 And it's also available from Amazon.com for the Kindle in the final form.
00:09:47 So we are only waiting for the print book at this time.
00:09:50 Right.
00:09:51 Okay.
00:09:51 Excellent.
00:09:52 Yeah.
00:09:52 I think having the electronic book works really well.
00:09:55 I was reading it on my Kindle and it, on my Kindle, paper white, and it was really nice.
00:09:59 You know, the code samples came through really well.
00:10:02 Like sometimes that doesn't work so well.
00:10:04 Wow.
00:10:04 That's cool.
00:10:05 Nice to know.
00:10:05 Yeah.
00:10:06 Yeah.
00:10:06 It came out really, really well.
00:10:07 And, you know, so I've only had the book for a few days.
00:10:11 So I've only been able to read maybe the first five chapters.
00:10:14 But my impression of the first five chapters, if it keeps going like this, I'm sure it does, is this book is a masterpiece.
00:10:22 It is really, really good.
00:10:25 Well, thank you very much.
00:10:26 I think it's going to go down as a classic book in the Python community.
00:10:29 Really.
00:10:30 Thank you very much.
00:10:31 Yeah.
00:10:31 I'm not just saying that because you're on the show.
00:10:33 But I was reading it and it's a little hard for me to put in words, I think, for people to really understand.
00:10:41 But it seemed like everything that you covered, and we'll talk a bit more about that.
00:10:46 But it seemed like everything you covered, I'm kind of like, I mostly know this.
00:10:49 Oh, wait.
00:10:50 There's this really cool piece of information or motivation that I was never really aware of.
00:10:57 And just underneath the surface of the knowledge that I do have.
00:11:02 Right.
00:11:02 And that was like all the time happening to me while I was reading your book.
00:11:06 And so I think it's a great contribution.
00:11:08 Thank you.
00:11:09 Yeah.
00:11:10 So let me read a quick quote right from the beginning to give people a sense of, I think, what you're going for with this book.
00:11:17 So in the introduction or one of the first chapters, you say, Python is an easy-to-learn, powerful programming language.
00:11:24 Those are the first words of the official Python tutorial.
00:11:26 That's true, but there's a catch.
00:11:28 Because the language is so easy to learn and put to use, many practicing Python programmers leverage only a fraction of its powerful features.
00:11:35 Does that kind of sum up the problem you're trying to solve with this book?
00:11:40 Exactly.
00:11:41 And that's why I called it Fluent Python.
00:11:42 You know, as somebody who is fluent in two languages, in Portuguese and English, and that knows how difficult it is to become fluent in a language,
00:11:52 because it's easy to become fluent in the language in your native language, right?
00:11:56 You grow with it, and that's basically people don't even notice.
00:12:01 But getting fluent in another language is hard.
00:12:05 And so I've been teaching Python to lots of people.
00:12:11 When I had a company, whenever we hired people, we never could hire people that knew Python because nobody knew Python at the time.
00:12:18 So we hired people who knew Java and then taught them Python.
00:12:22 But I also worked as a Python instructor, and that's what I do now these days.
00:12:28 So I realized that this thing that I say over there, that the language is easy to use, it's practical.
00:12:36 So people start solving real problems real fast.
00:12:40 But that means that sometimes they are already using it for several years and don't know why some things are the way they are.
00:12:47 And another thing that I say right after that in the second paragraph is that when you're learning a new language,
00:12:57 you look for things that are familiar to you.
00:13:01 Like, for instance, maybe this language, probably this language has a way to use a regular expression.
00:13:08 Let's see how that works.
00:13:09 But if there is something in the language that is not matched by something that you know from another language,
00:13:17 like, for instance, the concept of generators that many languages don't have,
00:13:22 then you're unlikely to go look for it, right?
00:13:25 Because you don't even know the thing exists.
00:13:27 Another simpler example than generators is like tuple unpacking.
00:13:32 It's just a nice synthetic sugar.
00:13:35 But if you've never seen that in a language, you won't look for it.
00:13:39 And maybe you're going to spend years working with Python without ever using it.
00:13:43 But it's a really nice thing to use because it makes code more readable, even safer in some ways.
00:13:49 Python tuple unpacking has this characteristic because it actually forces the interpreter to count the number of items.
00:13:59 So if there's one more or one less, an error will be raised.
00:14:03 So it's a very nice feature, but it's something that people who come from other languages may never use because they won't think about it.
00:14:10 Right.
00:14:10 If you came from something like C#, for example, that doesn't have this concept of tuple unpacking,
00:14:15 and so you just wouldn't even, you might not ever find it.
00:14:19 And that kind of gets at the broader issue or concept of Pythonic versus non-Pythonic code, right?
00:14:29 Yes.
00:14:29 Yes.
00:14:30 It's pretty easy to come over to Python and learn it really quickly so that you can do the same thing that you do.
00:14:37 But it's not always the best, is it?
00:14:39 Some of your mental models don't really carry over so well.
00:14:42 Exactly.
00:14:43 Yeah.
00:14:43 Yeah.
00:14:44 It's very, it's, of course, it's a very elusive thing to define what is Pythonic.
00:14:51 I actually mentioned it several times in the book and tried to address it afterwards.
00:14:58 But basically, I just send people links to other people that I respect a lot in the Python community who have attempted to define it directly.
00:15:11 Right.
00:15:11 But it's like, it's about a good definition which doesn't really explain what is Pythonic is to say it's idiomatic Python, right?
00:15:20 Right.
00:15:21 But okay, so what is idiomatic Python?
00:15:23 Right?
00:15:24 It's hard to define.
00:15:27 Yeah.
00:15:28 I think your best bet is to show a bunch of people a bunch of examples, say, all of these things are Pythonic.
00:15:34 All of these things are not Pythonic because they carry over concepts that work well in other languages but are not the proper way to do them here.
00:15:44 And once you get enough experience of going, bad example, good example, then you kind of get this sense, like almost a smell for like, yeah, it seems like this is right.
00:15:54 It seems like that's not right.
00:15:55 But it's very hard to be very concrete.
00:15:57 Exactly.
00:15:58 Yeah.
00:15:59 Yeah.
00:15:59 I tried to do that in the book.
00:16:01 And actually, a decision that I made early on was to be as Pythonic as I could in the program examples, even when being Pythonic might not have provided the clearest source code from something that's not familiar with the language.
00:16:20 You know?
00:16:21 Like, for instance, right in the first example in the book, I use named tuple, right?
00:16:29 Yep.
00:16:29 And then I give it just a couple sentences to explain.
00:16:34 It's probably not enough if the person has never seen it, but it's actually something useful that I start using all over the book.
00:16:41 And if that picks up the person's curiosity, then the person can go and look for it.
00:16:48 So this is what I decided.
00:16:50 Like, for instance, before I actually have a chapter that formally discusses generated expressions, I use them in the book whenever it was natural to do so.
00:16:59 Even before I actually cover it.
00:17:02 Because of what I just said.
00:17:03 You know, I wanted to write idiomatic Python whenever I could, even if that made the...
00:17:09 Because the thing is, when you're speaking to a native speaker of English, for example, the person won't dumb down his or her speech for you, right?
00:17:21 That's right.
00:17:22 And that's cool.
00:17:23 Sometimes maybe you don't understand everything, but you're catching, you know, there's something new about the way this person is expressing herself.
00:17:33 And then you're going to try and find out what that means.
00:17:37 That's, you know, if you always talk to people that spoke English, easy English, you would only learn easy English and not real English, fluent English.
00:17:49 You wouldn't get that chance to grow into a fluent speaker, kind of like you said.
00:17:53 So your example with the name tuple kind of hits on the point that I was talking about.
00:17:58 Like, I've used name tuples.
00:18:00 I'm familiar with them.
00:18:01 I think they're great.
00:18:02 But, you know, you go a little bit deeper and you're like, hey, it's really cool to use a name tuple because the actual dictionary that stores the attributes is stored in the class object, which is a singleton in the runtime.
00:18:16 Not in the individual instances.
00:18:17 So storage is actually cheaper than regular custom classes.
00:18:21 Yes.
00:18:21 So if all you want to have is just a bunch of pieces of data that have names in an object, but not functionality, maybe you should use these name tuples.
00:18:31 This episode is brought to you by Hired.
00:18:44 Hired is a two-sided, curated marketplace that connects the world's knowledge workers to the best opportunities.
00:18:50 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:18:59 Typically, candidates receive five or more offers in just the first week, and there are no obligations.
00:19:05 Ever.
00:19:05 Sounds pretty awesome, doesn't it?
00:19:07 Well, did I mention there's a signing bonus?
00:19:10 Everyone who accepts a job from Hired gets a $2,000 signing bonus, and as Talk Python listeners, it gets way sweeter.
00:19:18 Use the link Hired.com slash Talk Python To Me, and Hired will double the signing bonus to $4,000.
00:19:25 Opportunities knocking.
00:19:27 Visit Hired.com slash Talk Python To Me and answer the call.
00:19:31 Exactly.
00:19:41 Yeah.
00:19:42 And another thing.
00:19:43 They are, because they are inexpensive, you can use it.
00:19:47 And they are inexpensive and they are completely compatible with tuples, right?
00:19:52 You can unpack them, you can iterate over the items and so on.
00:19:55 So, for instance, whenever you need to return more than one value from a function, I recommend you return a name tuple.
00:20:03 Because it will make, for instance, understanding what the function does easier, because there's going to be the definition of this name tuple.
00:20:11 If the person is looking at the result of the function in the console or in the debugger, the person is going to actually see the names of the parts of the tuple that the function is returning.
00:20:24 So, this is a recommendation.
00:20:26 Like, for instance, if you're going to return more than one value from a function, usually people do it with a tuple, and that's fine.
00:20:34 But with the name tuple is even better.
00:20:36 And it's cheap, like you said, because of the way it's implemented.
00:20:40 It doesn't require more memory.
00:20:44 Yeah.
00:20:45 You don't have to store all the keys, copies of the keys for every instance, right?
00:20:49 Like you would with regular classes or objects.
00:20:52 Yeah.
00:20:53 And, of course, when those come back, if you're unsure what's coming back from that method, you could print it out and you get a nice listing of actually not just what's in there, but the meaning of them by the name.
00:21:02 Exactly.
00:21:03 Exactly.
00:21:03 Or if you're in a debugger like PyCharm, you could probably hover over it and actually see it pop up in the watch window.
00:21:10 Yeah, it's excellent.
00:21:11 Yeah.
00:21:11 Yeah.
00:21:12 So, one thing that you said you used in your book is something called Doctest to check the code in the console listings.
00:21:18 Can you talk about that a little bit?
00:21:20 Yeah.
00:21:20 So, that's something that I think was created by the people in the ZOOP community.
00:21:28 And it's not...
00:21:32 So, in the ZOOP community, this was always very big.
00:21:35 So, the main idea of Doctest is to make sure that whatever code snippets appear in documentation, particularly listings of console sessions demonstrating stuff, that those actually match the behavior of the program at that time.
00:21:56 So, this was the starting point for Doctest.
00:22:01 In the ZOOP community, which is still active, there's a lot of development going on still in ZOOP.
00:22:07 There's a lot of also files that are testing files that are not strictly documentation that are written in the Doctest format.
00:22:18 Because it's really easy to...
00:22:19 Because it's really easy to...
00:22:20 I find it excellent to...
00:22:22 When I have to design a new API.
00:22:24 Because I...
00:22:27 It's sort of a BDD thing, you know?
00:22:30 You start typing those fake console sessions where you're thinking how it would feel to interact with this API.
00:22:41 And then the result would look like that and so on.
00:22:44 And then you...
00:22:46 It's really good to do TDD.
00:22:49 Because you write a couple of stanzas of Doctest and then you implement the code that makes it pass and so on and on and on.
00:22:59 You know, the whole idea of trying to envision what your API looks like from the outside and then implement it generates much cleaner APIs in the end.
00:23:10 And this is, you know, one flavor of that, right?
00:23:12 That's cool.
00:23:12 Yeah.
00:23:14 One thing, though, I have to say about Doctest is that after a while you'll realize there are some limitations to it.
00:23:20 And even recently, like last week, I was...
00:23:24 I had to come up with a difficult solution to an algorithmic problem.
00:23:29 And I started implementing some tests using Doctests.
00:23:34 But then, for instance, Doctest doesn't let you easily run just one part of the test.
00:23:40 It runs everything from top to down.
00:23:43 And sometimes when you're debugging, it's useful to be able to run just a specific part.
00:23:48 Anyway, the unit testing frameworks, not only unit tests, but py tests, which is my favorite, are much more powerful than Doctests.
00:23:59 And they can actually also run Doctests.
00:24:02 So there is a way to integrate them.
00:24:04 So you can have...
00:24:05 I think the best idea these days is to really use Doctests just for the documentation.
00:24:13 And just the straightforward cases, not corner cases, not weird outcomes, not testing whether an exception is raised or not.
00:24:23 Because although all of that can be done in Doctests, in the end, it becomes difficult to maintain the tests.
00:24:30 Right.
00:24:30 Maybe it's better done in pytest, something like that.
00:24:32 Exactly.
00:24:33 Yeah.
00:24:33 I use Py.Test.
00:24:35 I prefer it much better than unit tests because I think unit tests has a very strong Java flavor of forcing you to do everything inside classes.
00:24:44 Mm-hmm.
00:24:44 And I much prefer the syntax that pytest introduced and the nodes also supports.
00:24:50 But I prefer Py.Test of having tests as functions.
00:24:54 And you can create classes if you want, but you can also have module level things.
00:24:58 I prefer the syntax.
00:25:01 Yeah, cool.
00:25:03 So one of the very first things that you talk about in your book is the Python data model.
00:25:08 And you talk about it's sort of the foundation for making your own classes fit this Pythonic programming model.
00:25:17 And you have a quote in there.
00:25:18 It's something like the – you know, talking about this data model or just learning about it is the tip of the iceberg.
00:25:25 So the iceberg is called the Python data model, and it describes the API that you can use to make your own objects play well with the most idiomatic language features.
00:25:33 Yes.
00:25:34 Mm-hmm.
00:25:35 Do you think people are – people who are sort of come to Python from other languages, you know, ones that add functionality to their classes very much by overriding virtual methods and those kinds of things sort of miss out on some of the Python data model, like under-under init or, you know, the iter or str methods, things like that?
00:25:57 Yeah, for instance, this is something that happened to me many years ago when I developed the French deck, the card deck example that I use in that chapter.
00:26:08 So many years ago when I had the idea of implementing that, so I was – the idea was to show how easy it was to create a new class that behaved like a sequence, right?
00:26:25 So you implement dunder lan and you implement dunder get item and basically you are done.
00:26:31 But then something really interesting happened because I was implementing – the idea was to implement a card deck, right?
00:26:37 So what is an obvious thing you want to do with a card deck is to shuffle it, right?
00:26:41 Right.
00:26:42 So the first time that I created this example, I actually had a method called shuffle, which was not a special method.
00:26:50 It was not dunder shuffle.
00:26:51 It was just shuffle, right?
00:26:53 So the idea was – so you have this card deck and you can look at the cards and you can call the shuffle method and see the cards shuffle.
00:27:00 Okay.
00:27:01 But then a few weeks after that, I realized that when I looked back at the example given a class, I said, wait, wait a minute.
00:27:14 There is already a shuffle function in the random module that shuffles any mutable sequence that you give it.
00:27:27 So it actually doesn't make sense to implement the shuffle.
00:27:31 If the whole point of my exercise was to show how easy it was to create a sequence, even if the sequence represented a card deck, a very specific domain, specific thing, it didn't make sense for me to implement my own shuffle method.
00:27:47 Because there was already a shuffle method and it is designed to work with mutable sequences.
00:27:54 Right.
00:27:55 Right.
00:27:55 And it's already tested, probably optimized, all that kind of stuff, right?
00:27:58 Exactly.
00:27:59 So then that was an insight for me of an advantage of being Pythonic.
00:28:05 It's the fact that when you are Pythonic, your objects suddenly become more compatible with things that are already out there in the standard library and in other packages that you can download from PyPI.
00:28:19 Yeah, I think this is a lesson that people need to learn.
00:28:24 Because, for instance, I don't know about C#.
00:28:29 I studied Java a lot for a while.
00:28:31 And even today, sometimes I spend some time every year I try to sit down and read something about Java.
00:28:39 Because I get a lot of clients in my course that studied Java before and it's useful to make analogies.
00:28:47 But, for instance, a big advantage of Python over Java is the fact that we have these operators that are more generic.
00:28:55 Like, for instance, the square bracket operator, which is the operator to get an item or to set an item, right?
00:29:03 And they don't have that in Java.
00:29:07 That operator in Java is a magical thing that only works with the primitive arrays.
00:29:14 Anything else, you have to use some other, you know, you have to use method syntax.
00:29:20 Also, these days I'm studying Go, the Go language, and I really like it very much.
00:29:27 But one of the things that I most dislike about it is the fact that it follows this Java philosophy of having some built-in data structures that are magical.
00:29:38 And you cannot create your own data structures that emulate them precisely.
00:29:43 Like, for instance, in Go, there's a way to...
00:29:48 You can iterate over some primitive types, like maps and arrays and slices.
00:29:55 But you cannot create your own type that is iterable using the for-range construct of the language.
00:30:02 Right.
00:30:03 That's too bad.
00:30:04 Unlike the for-in-loop in Python, which is totally accessible.
00:30:08 Yeah, so I think Java, I think Python is actually better than most languages in this regard, of enabling you to create structures that behave exactly like the most fundamental data structures in the language.
00:30:22 And the way to accomplish that is through the data model.
00:30:25 So, I think it's very nice to have that documented and exposed, and I wanted to give it more visibility.
00:30:33 So, that's why I started the first chapter with that.
00:30:35 Even if in the following chapters, my strategy then is to say, okay, but let's look at what is already implemented in Python.
00:30:44 Because I didn't want people to go out and reimplementing new sequence types when maybe they don't even leverage everything that the built-in sequence types can offer.
00:30:55 Right?
00:30:56 Right.
00:30:56 I think that's a good point.
00:30:57 People coming from other languages, they don't necessarily know what's available.
00:31:01 So, they'll find themselves reimplementing stuff.
00:31:03 A really simple example would be I would like to randomly get an item out of a list.
00:31:09 So, I might import the random module, get a random index based on the length, and then go index it out.
00:31:14 Or you could just do random.choice.
00:31:16 Oh, I didn't know random.choice exists.
00:31:18 Exactly.
00:31:19 Yeah.
00:31:19 Yeah.
00:31:20 So, one thing that you talk about around the Python data model is the len method.
00:31:25 Mm-hmm.
00:31:26 Yeah.
00:31:27 And, you know, being such an object-oriented language, I always felt that it should be, you know, collection.len or length or something like that, maybe even as a property.
00:31:38 And this sort of special function on the outside of the classes seemed a little bit odd.
00:31:43 But you had a good conversation around that in there.
00:31:46 You want to elaborate on that?
00:31:47 Yeah.
00:31:48 Sure.
00:31:48 So, that is also something that bothered me for a while.
00:31:52 Of course, you get used to it because it's really easy to get used to it and it's really easy to type.
00:31:58 It's actually one of the arguments that Guido uses to defend that decision is that it's easier to type than having a dot.
00:32:05 You know, if it was a method call, you would have to write, like, you know, x.len open close paren.
00:32:14 Right?
00:32:15 So, there's one dot extra there.
00:32:19 And it's also something.
00:32:21 And here's another thing that's funny.
00:32:23 Because I think it's of the human nature.
00:32:28 When people come to learn a new language, sometimes they are not pleased.
00:32:33 Sometimes their boss told them to learn it.
00:32:35 Right?
00:32:37 And then, some people try to resist by pointing out, you know, things that they don't like or things that they think are inconsistent.
00:32:46 And bugs, although bugs are extremely difficult for a beginner to find in Python.
00:32:52 I've never seen a beginner find a bug in Python.
00:32:55 Every time a beginner thinks… I've seen them write bugs.
00:32:57 Yeah, yeah.
00:32:58 Sure.
00:32:58 Yeah.
00:33:00 But most of the time, in my life, every time I've seen a beginner complain about a Python bug in a mailing list, it was invariably because the person didn't understand what exactly was going on.
00:33:11 That's right.
00:33:11 It was not a real bug.
00:33:12 But anyway, here's about inconsistencies.
00:33:15 So, they say, ah, this is inconsistent because it should be spelled as a method.
00:33:21 Okay.
00:33:22 Now, let's think about how this problem is solved in Java.
00:33:26 In Java, there's actually an inconsistency because there is the… in the array type, there is like a… a property, as it were.
00:33:37 It's actually a field, like a public field that you read.
00:33:41 So, you don't… you just write myarray.length without parentheses, and that's how you get the length of the array.
00:33:50 Because Java is just basically giving you the value that's… it's internally stored in a structure that represents the array.
00:33:58 So, that's very cheap, and that's how they do it.
00:34:01 And it's important to be cheap because it's a very common operation.
00:34:05 Then, for other types that don't have this structure, there's a method called length.
00:34:12 But also, in the Java API, there are other classes that could perfectly have methods named length, but have methods named size.
00:34:21 Size or count or something, yeah.
00:34:23 Yeah.
00:34:24 So, there's at least three different ways that are common in Java code to do the same thing.
00:34:32 And in Python, we have only one way.
00:34:34 It's the length of the thing, called as a function.
00:34:37 And so, first of all, it's more consistent.
00:34:41 The second thing is, it's pragmatic.
00:34:44 Because the way it works is, if you say length of X, and X is a built-in type, this built-in type, if the built-in type has many elements,
00:34:56 there's actually a struct, I forgot the name, but it's spelled out in the book,
00:35:01 there's actually a C struct that represents the type, and it has a field that has the count of the numbers, of the number of items.
00:35:08 So, that's the same thing that Java does, except that it doesn't expose a special field, but uses the length function.
00:35:15 So, the length function, the implementation of the length function in the Python interpreter does that.
00:35:20 It just goes to look at, if there is a built-in type, and it's a multi-valued built-in type,
00:35:26 then return the value of this field in the struct.
00:35:29 So, that's very cheap, and it's actually faster than doing the resolution of an attribute, right?
00:35:36 So, because if you had to write X dot length, this dot requires some advanced machinery in Python,
00:35:43 because of the dynamic nature of Python.
00:35:45 The price we pay for all this dynamic behavior is that the dot operator is kind of expensive.
00:35:52 Right.
00:35:52 Basically, a dictionary lookup, and then the function calls themselves are also kind of expensive.
00:35:57 Exactly.
00:35:58 Yeah, and it's more expensive than a dictionary lookup, because there's all that machinery that I explain later in the book.
00:36:08 Basically, in the last part of the book, the metaprogramming part, is where I explain actually how descriptors work.
00:36:16 And descriptors, the infrastructure below properties, but also below another thing that's really fundamental that everybody uses in Python,
00:36:27 which are methods.
00:36:28 Because what makes a method behave as a method, as an instance method, as a bound method, or as an unbound method,
00:36:38 has to do with the way the descriptor mechanism resolves the dot operator.
00:36:45 So, it's an expensive thing.
00:36:47 So, by making it be written as len paren X, close paren, the interpreter can resolve this much faster.