WEBVTT 00:00:00.001 --> 00:00:04.780 How many Python developers do you know that learned Python quickly, but then plateaued 00:00:04.780 --> 00:00:09.000 pretty quickly as well? Maybe this is someone you worked with, or maybe it's even you. 00:00:09.000 --> 00:00:14.720 Python's clean and simple syntax can mean it's easy to learn, but hard to master. After all, 00:00:14.720 --> 00:00:18.560 if you learned it in a week, what else is there to this language? How much more do you need to 00:00:18.560 --> 00:00:25.200 dig into it? Well, plenty. And Dan Bader is here to share his very popular Python tricks with us. 00:00:25.320 --> 00:00:31.960 You'll learn to look deeper for more than just the how, but the why and when of many of Python's 00:00:31.960 --> 00:00:38.100 more subtle features. This is Talk Python To Me, episode 141, recorded December 4th, 2017. 00:00:51.480 --> 00:00:57.700 Welcome to Talk Python To Me, a weekly podcast on Python, the language, the libraries, the ecosystem, 00:00:57.700 --> 00:01:02.460 and the personalities. This is your host, Michael Kennedy. Follow me on Twitter, where I'm at 00:01:02.460 --> 00:01:08.000 mkennedy. Keep up with the show and listen to past episodes at talkpython.fm, and follow the show on 00:01:08.000 --> 00:01:14.760 Twitter via at Talk Python. This episode is brought to you by Linode and Rollbar. Thank them both for 00:01:14.760 --> 00:01:19.380 supporting the show by checking out what they have to offer during their segments. Talk Python To Me is 00:01:19.380 --> 00:01:25.400 partially supported by our training courses. Python's async and parallel programming support is highly 00:01:25.400 --> 00:01:30.060 underrated. Have you shied away from the amazing new async and await keywords because you've heard 00:01:30.060 --> 00:01:35.900 it's way too complicated or that it's just not worth the effort? With the right workloads, a hundred times 00:01:35.900 --> 00:01:41.460 speed up is totally possible with minor changes to your code. But you do need to understand the internals, 00:01:41.460 --> 00:01:47.440 and that's why our course, Async Techniques and Examples in Python, show you how to write async code 00:01:47.440 --> 00:01:53.260 successfully as well as how it works. Get started with async and await today with our course at 00:01:53.260 --> 00:01:59.660 talkpython.fm/async. Hey, everyone. Before we get to the conversation with Dan about his Python 00:01:59.660 --> 00:02:05.340 tricks, I want to talk about Python bytes for a second. I know many of you who listen to Talk Python 00:02:05.340 --> 00:02:11.380 also listen to my other podcast, Python bytes, but many of you don't, and it's been a while since I've 00:02:11.380 --> 00:02:17.180 talked about it on the show. So if you're looking for almost the opposite of Talk Python, instead of 00:02:17.180 --> 00:02:23.120 long form, deep conversations on one topic, you want to just catch up on the news, think newsletter and audio 00:02:23.120 --> 00:02:25.280 forum for the Python space, head over to 00:02:25.280 --> 00:02:28.340 pythonbytes.fm and subscribe to the short 00:02:28.340 --> 00:02:31.460 news focused 15 minute weekly podcast 00:02:31.460 --> 00:02:35.340 I do with Brian Okken. I hope you guys check it out and I hope you're enjoying both 00:02:35.340 --> 00:02:39.340 of the podcasts. Now let's chat with Dan. Dan, welcome back 00:02:39.340 --> 00:02:41.440 to Talk Python. Hey, thanks, Mike. Thanks for having 00:02:41.440 --> 00:02:43.320 me on the show again. Yeah, I love to talk with you 00:02:43.320 --> 00:02:45.380 about technology and programming, so I'm really 00:02:45.380 --> 00:02:47.000 excited to do it once again. 00:02:47.000 --> 00:02:49.020 You were previously on the show 00:02:49.020 --> 00:02:51.540 for our panel with 00:02:51.540 --> 00:02:53.060 Anthony and Ronald about 00:02:53.060 --> 00:02:55.240 Contributed Open Source, and that was really a well-received 00:02:55.240 --> 00:02:57.100 episode. That was 132. Cool, yeah. 00:02:57.100 --> 00:02:59.340 That was a really fun experience, and 00:02:59.340 --> 00:03:01.160 I really like the panel format. You know, I 00:03:01.160 --> 00:03:03.240 listen to your show, and those are 00:03:03.240 --> 00:03:05.280 some of my favorite episodes when you bring on a bunch of 00:03:05.280 --> 00:03:07.280 people, and it's just, you know, the amount of information 00:03:07.280 --> 00:03:10.800 you can soak up so quickly. It's, yeah, it's just great. 00:03:10.800 --> 00:03:13.020 Awesome, thanks. The next one that I have scheduled, 00:03:13.020 --> 00:03:15.240 I don't know when it's actually going to air, like 00:03:15.240 --> 00:03:17.340 four or five episodes out, is 00:03:17.340 --> 00:03:19.160 a catch-up for 00:03:19.160 --> 00:03:21.500 Python and machine learning at the Large Hadron 00:03:21.500 --> 00:03:23.160 Collider and in particle physics, 00:03:23.160 --> 00:03:25.060 so that should be really fun. That sounds intense. 00:03:25.060 --> 00:03:27.380 It's going to be intense. That means lots of research 00:03:27.380 --> 00:03:29.040 for me, so that'll be awesome. All right, 00:03:29.040 --> 00:03:31.140 so let's talk about 00:03:31.140 --> 00:03:33.680 not contributing to Open Source so much. 00:03:33.680 --> 00:03:35.400 Let's talk about making our 00:03:35.400 --> 00:03:37.280 Python better with Python 00:03:37.280 --> 00:03:39.340 tricks. So that's what we're going to talk about this 00:03:39.340 --> 00:03:41.440 week. You know, I know you talked a little 00:03:41.440 --> 00:03:43.240 bit about it in 132, episode 00:03:43.240 --> 00:03:45.340 132, but it was the panel format, 00:03:45.340 --> 00:03:47.080 so you didn't get to go into it too much. 00:03:47.080 --> 00:03:49.300 So let's talk just quickly, kind of like 00:03:49.300 --> 00:03:51.280 how you got into programming and what you 00:03:51.280 --> 00:03:52.920 do day-to-day before we get into your tricks. 00:03:52.920 --> 00:03:55.260 Sounds good, yeah. So, well, I guess how I got 00:03:55.260 --> 00:03:57.260 into programming was when I 00:03:57.260 --> 00:03:59.620 finally managed to convince my parents to buy 00:03:59.620 --> 00:04:01.780 a used, old, dingy 00:04:01.780 --> 00:04:03.160 Commodore 64 for me. 00:04:03.160 --> 00:04:05.480 And, you know, that was the end of the 00:04:05.480 --> 00:04:07.620 home computing era, I guess, and those machines 00:04:07.620 --> 00:04:09.040 all booted into some kind of 00:04:09.040 --> 00:04:11.500 interpreter directly, so you wouldn't, you know, 00:04:11.500 --> 00:04:13.420 you don't get, like, a graphical desktop 00:04:13.420 --> 00:04:15.280 or anything. You just get a basic, the 00:04:15.280 --> 00:04:16.060 programming language. 00:04:16.060 --> 00:04:17.460 Yeah, that was crazy because you would, 00:04:17.460 --> 00:04:19.200 like, you couldn't just interact with the 00:04:19.200 --> 00:04:21.020 computer. You had to, like, 00:04:21.020 --> 00:04:23.600 converse with it to get it to do things, 00:04:23.600 --> 00:04:24.660 right? It was interesting. 00:04:24.980 --> 00:04:26.640 Exactly. It was, like, a glorified 00:04:26.640 --> 00:04:28.240 calculator and you just 00:04:28.240 --> 00:04:29.500 turned it on and you booted 00:04:29.500 --> 00:04:31.440 instantly and then you were just 00:04:31.440 --> 00:04:33.420 sitting there like, ah, okay, I'm 00:04:33.420 --> 00:04:34.440 getting this blue screen. 00:04:34.440 --> 00:04:36.840 What am I going to do now? 00:04:36.840 --> 00:04:38.520 And it really forced you to 00:04:38.520 --> 00:04:41.000 pick up some basic programming skills 00:04:41.000 --> 00:04:42.780 to do anything. You know, if you wanted 00:04:42.780 --> 00:04:44.940 to play a game, well, tough luck. 00:04:44.940 --> 00:04:46.380 You had to actually figure out, like, 00:04:46.380 --> 00:04:48.820 how to load the game from disk and 00:04:48.820 --> 00:04:50.120 then run it or, you know, actually 00:04:50.120 --> 00:04:50.680 type it in. 00:04:50.680 --> 00:04:52.340 Yeah, it was, like, a load command and 00:04:52.340 --> 00:04:53.520 stuff to actually do it, right? 00:04:53.760 --> 00:04:56.380 Exactly. Yeah, the load 8,1 or 00:04:56.380 --> 00:04:57.900 something. It's like the drive ID. 00:04:57.900 --> 00:05:00.520 And I think I'm kind of fortunate that 00:05:00.520 --> 00:05:02.540 I caught the tail end of that because 00:05:02.540 --> 00:05:04.320 it was already, like, the PC era and, 00:05:04.320 --> 00:05:07.140 like, Windows 3.11 or something. 00:05:07.140 --> 00:05:09.360 But because my parents were really, 00:05:09.360 --> 00:05:12.140 really against computers and technology 00:05:12.140 --> 00:05:14.120 in some way, the only thing I managed 00:05:14.120 --> 00:05:15.600 to convince him was to get this, you 00:05:15.600 --> 00:05:16.960 know, used old Commodore 64. 00:05:16.960 --> 00:05:18.640 And I got it from this guy and it came 00:05:18.640 --> 00:05:20.980 with, like, stacks of disks and 00:05:20.980 --> 00:05:22.660 notes this guy took. 00:05:22.660 --> 00:05:25.000 And so it was just a treasure trove for 00:05:25.000 --> 00:05:25.300 me. 00:05:25.300 --> 00:05:27.020 And, you know, it hooked up directly to 00:05:27.020 --> 00:05:29.500 your TV screen and it was just, yeah, 00:05:29.500 --> 00:05:31.840 just this amazing, like, miracle 00:05:31.840 --> 00:05:32.600 machine. 00:05:32.600 --> 00:05:34.300 And that's how I got into programming. 00:05:34.300 --> 00:05:35.700 Nice. And then how'd you get over to 00:05:35.700 --> 00:05:36.000 Python? 00:05:36.000 --> 00:05:36.980 Oh, yeah, that's a long, 00:05:36.980 --> 00:05:39.760 that's a long jump, a big leap there. 00:05:39.760 --> 00:05:39.980 Yeah. 00:05:39.980 --> 00:05:40.540 Right. 00:05:40.700 --> 00:05:43.060 I think that the basic programming and 00:05:43.060 --> 00:05:44.440 basic on the Commodore 64, I think it 00:05:44.440 --> 00:05:46.680 just kindled some, some kind of passion 00:05:46.680 --> 00:05:47.060 in me. 00:05:47.060 --> 00:05:49.020 And eventually I went on and got 00:05:49.020 --> 00:05:50.360 bachelor's and master's degree in 00:05:50.360 --> 00:05:52.900 computer science and just, you know, 00:05:52.900 --> 00:05:54.220 wanted to become a professional 00:05:54.220 --> 00:05:54.780 programmer. 00:05:54.780 --> 00:05:57.640 At some point in my university days, I 00:05:57.640 --> 00:05:59.140 think it was on a ski trip with some 00:05:59.140 --> 00:06:02.640 friends and one person, he brought a 00:06:02.640 --> 00:06:05.180 book, a Python programming book, one of 00:06:05.180 --> 00:06:07.340 these, like, learn Python in 48 hours. 00:06:07.340 --> 00:06:08.780 One of those that never really work out 00:06:08.780 --> 00:06:10.840 that way. And this was the first time 00:06:10.840 --> 00:06:11.140 I really. 00:06:11.140 --> 00:06:13.980 Was that the Sam's Learn Python on a 00:06:13.980 --> 00:06:16.420 Ski Vacation or Your Money Back 00:06:16.420 --> 00:06:17.400 Guaranteed book? 00:06:17.400 --> 00:06:19.240 Yeah, I should ask for my money back. 00:06:19.240 --> 00:06:20.300 Remember the Sam's book? 00:06:20.300 --> 00:06:22.380 It's awesome. So you had the book and 00:06:22.380 --> 00:06:23.580 you had some, like, kind of downtime 00:06:23.580 --> 00:06:26.080 after you're skiing to chill and flip 00:06:26.080 --> 00:06:26.400 through it? 00:06:26.400 --> 00:06:28.560 Yeah, it was a very geeky skiing trip. 00:06:28.560 --> 00:06:30.300 But this is when, the first time when 00:06:30.300 --> 00:06:31.800 I saw the actual language, you know, 00:06:31.800 --> 00:06:32.960 just learned a little bit more about 00:06:32.960 --> 00:06:34.240 it because my friend, he actually 00:06:34.240 --> 00:06:36.580 couldn't, hadn't used Python either, 00:06:36.580 --> 00:06:37.840 but it just seemed like an 00:06:37.840 --> 00:06:39.240 interesting new language or, you know, 00:06:39.240 --> 00:06:40.760 I guess it wasn't new at the time, but 00:06:40.760 --> 00:06:41.560 for us it was new. 00:06:41.560 --> 00:06:44.640 And so I just really fell in love with 00:06:44.640 --> 00:06:46.000 the way the language looked, you know, 00:06:46.000 --> 00:06:47.720 just seemed like the perfect blend of, 00:06:47.720 --> 00:06:50.000 well, this looks really appealing, you 00:06:50.000 --> 00:06:51.700 know, like almost like pseudo code and 00:06:51.700 --> 00:06:53.200 like in some way, like really poetic 00:06:53.200 --> 00:06:55.780 and nice, but also really, really 00:06:55.780 --> 00:06:58.120 powerful where it's not just your 00:06:58.120 --> 00:07:00.680 basic or basic programming language, but 00:07:00.680 --> 00:07:02.380 it's actually something where you can 00:07:02.380 --> 00:07:04.760 take it to places and you can build 00:07:04.760 --> 00:07:05.780 full-blown applications. 00:07:06.200 --> 00:07:07.300 And so, yeah, that's how it started. 00:07:07.300 --> 00:07:07.940 That's awesome. 00:07:07.940 --> 00:07:09.940 There's plenty of simple 00:07:09.940 --> 00:07:11.800 programming languages, but they often 00:07:11.800 --> 00:07:13.680 have like a ceiling where it's like, 00:07:13.680 --> 00:07:14.880 okay, you would build this and this 00:07:14.880 --> 00:07:15.880 with it, but you wouldn't really build 00:07:15.880 --> 00:07:17.880 anything bigger than that, right? 00:07:17.880 --> 00:07:19.080 Where it's pretty sweet that Python 00:07:19.080 --> 00:07:21.200 generally doesn't fall into that category. 00:07:21.200 --> 00:07:21.780 Yeah, totally. 00:07:21.780 --> 00:07:23.600 And I think it was you, you called it 00:07:23.600 --> 00:07:25.720 a full-spectrum language at some 00:07:25.720 --> 00:07:27.180 point or like on that interview that 00:07:27.180 --> 00:07:28.000 we did on my blog. 00:07:28.000 --> 00:07:30.300 And this is, I love this, you know, I 00:07:30.300 --> 00:07:31.360 bring this up all the time when 00:07:31.360 --> 00:07:32.780 people ask me about Python because 00:07:32.780 --> 00:07:35.320 yeah, it is really a full-spectrum 00:07:35.320 --> 00:07:36.940 language where someone can dive in and 00:07:36.940 --> 00:07:38.980 they can learn the basics of Python and 00:07:38.980 --> 00:07:40.200 know enough to be dangerous. 00:07:40.200 --> 00:07:43.460 And then you have giant, very, very 00:07:43.460 --> 00:07:45.200 complex systems built in this language 00:07:45.200 --> 00:07:47.520 and it can kind of scale that whole 00:07:47.520 --> 00:07:47.920 gamut. 00:07:47.920 --> 00:07:49.800 And I think that's just really cool. 00:07:49.800 --> 00:07:50.460 Yeah, it's amazing. 00:07:50.460 --> 00:07:52.740 What I really like about that spectrum is 00:07:52.740 --> 00:07:55.740 a lot of languages make you take the 00:07:55.740 --> 00:07:58.100 stuff you need for the advanced type of 00:07:58.100 --> 00:07:59.060 large applications. 00:07:59.160 --> 00:08:01.060 you got to use that syntax and that 00:08:01.060 --> 00:08:02.860 structure and those design patterns 00:08:02.860 --> 00:08:05.340 right from the start, like Java or C 00:08:05.340 --> 00:08:07.280 sharp static main void inside of a 00:08:07.280 --> 00:08:08.020 program class. 00:08:08.020 --> 00:08:09.020 You're like, whoa, I just want to like 00:08:09.020 --> 00:08:09.680 do a few things. 00:08:09.680 --> 00:08:10.640 Like what's all this about, right? 00:08:10.640 --> 00:08:12.480 Whereas Python, you like as you need the 00:08:12.480 --> 00:08:14.700 features, you layer them in, but they're 00:08:14.700 --> 00:08:16.280 not required until you need them, which 00:08:16.280 --> 00:08:17.340 is, I think, a part of the magic. 00:08:17.340 --> 00:08:18.960 That's a huge part of the appeal of 00:08:18.960 --> 00:08:20.800 Python that I see, you know, when people 00:08:20.800 --> 00:08:22.160 use Python or learn about Python, but 00:08:22.160 --> 00:08:24.360 it's also kind of the dirty little 00:08:24.360 --> 00:08:26.280 secret where it's very easy to kind of 00:08:26.280 --> 00:08:28.240 get stuck at that beginner level. 00:08:28.240 --> 00:08:30.060 And you're like, well, okay, so how 00:08:30.060 --> 00:08:31.780 would I actually go to the point where 00:08:31.780 --> 00:08:33.860 I could build, I don't know, something 00:08:33.860 --> 00:08:36.320 like the Instagram backend or even, you 00:08:36.320 --> 00:08:37.060 know, think about it. 00:08:37.060 --> 00:08:37.700 Yeah, absolutely. 00:08:37.700 --> 00:08:40.660 And that is one of the curses of its 00:08:40.660 --> 00:08:42.680 sort of success or its features is that 00:08:42.680 --> 00:08:44.540 it's a lot of people quickly get into 00:08:44.540 --> 00:08:45.680 it and they just get comfortable and 00:08:45.680 --> 00:08:47.340 they're just like, well, I just sort of, 00:08:47.340 --> 00:08:48.980 I knew C or I knew JavaScript. 00:08:48.980 --> 00:08:50.120 So now I know Python. 00:08:50.120 --> 00:08:52.160 I just don't do semicolons or curly 00:08:52.160 --> 00:08:52.840 braces, right? 00:08:53.500 --> 00:08:54.280 That's okay. 00:08:54.280 --> 00:08:55.000 And it works. 00:08:55.000 --> 00:08:57.880 But, you know, I think our topic today 00:08:57.880 --> 00:09:01.520 is really about understanding like where 00:09:01.520 --> 00:09:03.120 people get stuck and then going, okay, 00:09:03.120 --> 00:09:05.340 these are actually how you should go 00:09:05.340 --> 00:09:07.260 farther and do it correctly or 00:09:07.260 --> 00:09:08.780 Pythonically or whatever, right? 00:09:08.780 --> 00:09:10.420 Yeah, pretty, pretty much. 00:09:10.420 --> 00:09:12.300 I mean, this is, I feel like this is the 00:09:12.300 --> 00:09:14.100 biggest challenge in taking the next 00:09:14.100 --> 00:09:15.000 step with Python. 00:09:15.000 --> 00:09:16.880 Like how, you know, what does it even 00:09:16.880 --> 00:09:19.000 mean to write Pythonic code and how, 00:09:19.000 --> 00:09:19.880 how do you get there? 00:09:19.880 --> 00:09:22.860 because it's such an opaque concept and 00:09:22.860 --> 00:09:24.180 yeah, and whatever can be done there, 00:09:24.180 --> 00:09:25.380 I think it's going to make people's 00:09:25.380 --> 00:09:26.840 lives easier and it's going to make 00:09:26.840 --> 00:09:28.160 them more successful as developers. 00:09:28.160 --> 00:09:28.940 Yeah, absolutely. 00:09:28.940 --> 00:09:31.340 So let's talk about your book, Python 00:09:31.340 --> 00:09:32.240 Tricks. 00:09:32.240 --> 00:09:35.440 It's a buffet of awesome Python features, 00:09:35.440 --> 00:09:36.460 which is really nice. 00:09:36.460 --> 00:09:39.520 And you released it a little while ago 00:09:39.520 --> 00:09:42.120 in a digital only version on your site, 00:09:42.120 --> 00:09:43.940 debater.org, right? 00:09:43.940 --> 00:09:44.680 Right URL? 00:09:44.680 --> 00:09:45.220 That's right. 00:09:45.220 --> 00:09:45.440 Yeah. 00:09:45.440 --> 00:09:45.640 Yeah. 00:09:45.640 --> 00:09:49.040 And you also released it on Amazon and 00:09:49.040 --> 00:09:50.960 it kind of went a little bit crazy on 00:09:50.960 --> 00:09:51.260 Amazon. 00:09:51.260 --> 00:09:52.220 Well done, man. 00:09:52.220 --> 00:09:52.680 Thank you. 00:09:52.680 --> 00:09:53.400 How did it do? 00:09:53.400 --> 00:09:54.800 Like right now, if I'm looking here, 00:09:54.800 --> 00:09:58.780 it's number 21 and all the books in 00:09:58.780 --> 00:10:00.800 Python, like that's amazing for such a 00:10:00.800 --> 00:10:03.420 new book, but it was much higher, right? 00:10:03.420 --> 00:10:03.760 Yeah. 00:10:03.760 --> 00:10:06.800 So crazy enough, it actually hit the 00:10:06.800 --> 00:10:08.880 number one spot in Python programming 00:10:08.880 --> 00:10:12.100 and in programming languages in general. 00:10:12.280 --> 00:10:14.840 At some point it was even, it was book, 00:10:14.840 --> 00:10:18.720 it ranked number 250 in Amazon sales 00:10:18.720 --> 00:10:20.800 rank across all books on Amazon. 00:10:20.800 --> 00:10:22.280 And, you know, I actually, I took a 00:10:22.280 --> 00:10:24.400 screenshot of that and this is like. 00:10:24.400 --> 00:10:27.240 Printed out, put it on the wall in frame. 00:10:27.240 --> 00:10:29.440 This was like visible proof to my in-laws 00:10:29.440 --> 00:10:31.180 that I was just, you know, I was not, 00:10:31.180 --> 00:10:33.900 not unemployed, not just unemployed and 00:10:33.900 --> 00:10:35.360 addicted to the internet. 00:10:35.360 --> 00:10:38.260 It's like, here, I'm an author on the 00:10:38.260 --> 00:10:38.620 internet. 00:10:39.480 --> 00:10:41.180 This is what I've been doing in my 00:10:41.180 --> 00:10:41.520 office. 00:10:41.520 --> 00:10:43.100 I promise you I have a job. 00:10:43.100 --> 00:10:44.520 Yeah, it was a cool experience. 00:10:44.520 --> 00:10:45.360 That's really cool. 00:10:45.360 --> 00:10:46.000 Congratulations. 00:10:46.000 --> 00:10:46.760 Thank you. 00:10:46.760 --> 00:10:47.080 Yeah. 00:10:47.080 --> 00:10:47.380 Yeah. 00:10:47.380 --> 00:10:49.120 And so it's, it's still going strong. 00:10:49.120 --> 00:10:51.720 Like it's number 29 in web programming 00:10:51.720 --> 00:10:52.180 and stuff. 00:10:52.180 --> 00:10:53.600 So yeah, right now. 00:10:53.600 --> 00:10:54.000 Very cool. 00:10:54.000 --> 00:10:55.700 So we'll definitely link to your book 00:10:55.700 --> 00:10:56.880 from the show. 00:10:56.880 --> 00:10:58.880 So maybe give us the quick elevator 00:10:58.880 --> 00:10:59.900 pitch. 00:10:59.900 --> 00:11:01.220 I mean, we've kind of been building up 00:11:01.220 --> 00:11:02.540 to it, but what's the, what's the 00:11:02.540 --> 00:11:03.680 idea behind the book and what are you 00:11:03.680 --> 00:11:04.280 talking about in there? 00:11:04.280 --> 00:11:05.280 Well, like you said, the, the 00:11:05.280 --> 00:11:07.660 subtitle for a book is a buffet of 00:11:07.660 --> 00:11:08.700 awesome Python features. 00:11:08.700 --> 00:11:10.980 And so basically the book is a 00:11:10.980 --> 00:11:13.440 collection of actionable tips that 00:11:13.440 --> 00:11:15.600 will help you write clean, 00:11:15.600 --> 00:11:18.680 professional and developer style, 00:11:18.680 --> 00:11:20.460 quote unquote, Python code. 00:11:20.460 --> 00:11:22.840 And, you know, the feeling that I 00:11:22.840 --> 00:11:24.460 want to create for my readers is not 00:11:24.460 --> 00:11:26.140 like they're sitting through an 00:11:26.140 --> 00:11:27.760 advanced computer science lecture 00:11:27.760 --> 00:11:28.900 where I'm throwing a bunch of 00:11:28.900 --> 00:11:30.900 jargon at you, but more like we're 00:11:30.900 --> 00:11:32.600 on the same development team. 00:11:32.600 --> 00:11:33.640 You know, we're sitting down 00:11:33.640 --> 00:11:34.640 together, you know, maybe know the 00:11:34.640 --> 00:11:35.460 basics of Python. 00:11:35.760 --> 00:11:37.040 And I want to help you get up to 00:11:37.040 --> 00:11:38.700 speed as quickly as possible and 00:11:38.700 --> 00:11:39.920 help you grasp some of the 00:11:39.920 --> 00:11:41.320 intermediate and more advanced 00:11:41.320 --> 00:11:43.640 Python topics that often seem 00:11:43.640 --> 00:11:45.380 weird and opaque, you know, things 00:11:45.380 --> 00:11:46.740 like decorators, first class 00:11:46.740 --> 00:11:47.260 functions. 00:11:47.260 --> 00:11:48.940 What's the difference between an 00:11:48.940 --> 00:11:50.280 iterator and a generator and 00:11:50.280 --> 00:11:51.520 generator expressions and list 00:11:51.520 --> 00:11:52.200 comprehensions. 00:11:52.200 --> 00:11:54.080 And just some of the really useful 00:11:54.080 --> 00:11:57.680 things in Python that border on the 00:11:57.680 --> 00:11:59.960 arcane, but they're really not. 00:11:59.960 --> 00:12:01.860 If you, right. 00:12:01.860 --> 00:12:03.040 If you approach them from the right 00:12:03.040 --> 00:12:03.540 perspective. 00:12:03.820 --> 00:12:03.920 Sure. 00:12:03.920 --> 00:12:05.480 It's a lot of these things that, 00:12:05.480 --> 00:12:07.340 you know, I feel like Python is, you 00:12:07.340 --> 00:12:08.780 can learn the language really quick, 00:12:08.780 --> 00:12:10.520 but it takes a long time to really 00:12:10.520 --> 00:12:11.100 master it. 00:12:11.100 --> 00:12:12.360 And part of that mastery is like 00:12:12.360 --> 00:12:14.660 discovering these little trade-offs 00:12:14.660 --> 00:12:17.720 like I could use a tuple, but oh, by 00:12:17.720 --> 00:12:18.800 the way, did you know there's a name 00:12:18.800 --> 00:12:19.120 tuple? 00:12:19.120 --> 00:12:20.580 And did you know in Python three, six, 00:12:20.580 --> 00:12:21.920 there's a new version of a name 00:12:21.920 --> 00:12:23.600 tuple that is more flexible, but 00:12:23.600 --> 00:12:25.480 similar in performance and like, oh, 00:12:25.480 --> 00:12:27.080 wait, there's a new name tuple. 00:12:27.080 --> 00:12:27.560 What is that? 00:12:27.560 --> 00:12:27.860 Right. 00:12:28.280 --> 00:12:30.380 You don't really easily fall into 00:12:30.380 --> 00:12:32.600 that discovery or things like, yeah, 00:12:32.600 --> 00:12:34.740 you can use list as a queue, but it's 00:12:34.740 --> 00:12:37.060 like a thousand times slower than if 00:12:37.060 --> 00:12:39.220 you use this other proper thing for 00:12:39.220 --> 00:12:39.680 queuing. 00:12:39.680 --> 00:12:41.460 Oh, but don't use that for multi-thread 00:12:41.460 --> 00:12:42.920 and use this other one for, for 00:12:42.920 --> 00:12:44.660 parallelism and things like that. 00:12:44.660 --> 00:12:44.800 Right. 00:12:44.800 --> 00:12:46.400 Those types of things are somewhat 00:12:46.400 --> 00:12:48.200 arcane, but they're, they're not 00:12:48.200 --> 00:12:49.700 easily discoverable. 00:12:49.700 --> 00:12:50.320 I don't feel. 00:12:50.320 --> 00:12:50.860 Exactly. 00:12:51.020 --> 00:12:52.380 you know, where it's a lot of 00:12:52.380 --> 00:12:54.140 times like when someone has some 00:12:54.140 --> 00:12:55.720 experience with other programming 00:12:55.720 --> 00:12:56.800 languages and they're switching to 00:12:56.800 --> 00:12:58.660 Python, it can be really hard to 00:12:58.660 --> 00:12:59.880 understand how these different 00:12:59.880 --> 00:13:01.760 concepts map to Python, because I 00:13:01.760 --> 00:13:04.720 guess Python uses a very like human 00:13:04.720 --> 00:13:06.560 friendly naming style for a lot of 00:13:06.560 --> 00:13:07.520 things, you know, like you just 00:13:07.520 --> 00:13:08.700 mentioned the queue and list 00:13:08.700 --> 00:13:11.400 example, but if you're coming from, 00:13:11.400 --> 00:13:13.760 let's say a Java background, how 00:13:13.760 --> 00:13:15.820 does a list map to what I know from, 00:13:15.820 --> 00:13:17.460 from the Java world, you know, what, 00:13:17.460 --> 00:13:19.200 what kind of time complexity 00:13:19.200 --> 00:13:20.940 guarantees does it make and, and 00:13:20.940 --> 00:13:22.260 kind of, you know, touching on some 00:13:22.260 --> 00:13:23.080 of these things as well. 00:13:23.080 --> 00:13:25.180 Like how can you take some existing 00:13:25.180 --> 00:13:26.640 algorithm and actually bring it over 00:13:26.640 --> 00:13:28.620 to Python and to make sure, you 00:13:28.620 --> 00:13:29.820 know, it doesn't just look pretty, 00:13:29.820 --> 00:13:31.560 but it actually also really works 00:13:31.560 --> 00:13:32.400 and is fast enough. 00:13:32.400 --> 00:13:33.040 Yeah, absolutely. 00:13:33.040 --> 00:13:34.400 And one of the, you know, one of 00:13:34.400 --> 00:13:36.180 the things even more than like list 00:13:36.180 --> 00:13:38.840 versus say array list in Java is 00:13:38.840 --> 00:13:40.080 array, right? 00:13:40.080 --> 00:13:42.400 Like there's not really like the 00:13:42.400 --> 00:13:44.820 traditional C style array in Python 00:13:44.820 --> 00:13:46.920 in the built-in language sense. 00:13:46.920 --> 00:13:48.480 There's the, you know, array dot 00:13:48.480 --> 00:13:50.900 array class, but there's not the like, 00:13:50.900 --> 00:13:52.180 square bracket means something 00:13:52.180 --> 00:13:54.080 different than list, right? 00:13:54.080 --> 00:13:55.020 Like those are actually the same 00:13:55.020 --> 00:13:55.260 thing. 00:13:55.260 --> 00:13:57.860 And that just gets confusing, but I 00:13:57.860 --> 00:13:58.840 think we should probably just start 00:13:58.840 --> 00:14:00.520 going through some of your individual 00:14:00.520 --> 00:14:01.680 tricks that you thought are 00:14:01.680 --> 00:14:04.080 particularly like noteworthy in at 00:14:04.080 --> 00:14:06.440 least a radio format is. 00:14:06.440 --> 00:14:07.240 That'll be interesting. 00:14:07.240 --> 00:14:08.140 Yeah. 00:14:08.140 --> 00:14:09.760 It's so we'll try to not talk too 00:14:09.760 --> 00:14:11.100 much about code, but, you know, 00:14:11.100 --> 00:14:13.140 cover some of the ideas behind it. 00:14:13.140 --> 00:14:13.320 All right. 00:14:13.320 --> 00:14:15.280 So actually, you know, the first one 00:14:15.280 --> 00:14:16.500 you said, let's start with something 00:14:16.500 --> 00:14:16.860 simple. 00:14:16.860 --> 00:14:18.600 And I totally agree that it's a 00:14:18.600 --> 00:14:19.260 good place to start. 00:14:19.260 --> 00:14:21.780 You talk about comma placement for 00:14:21.780 --> 00:14:23.840 dictionaries and lists and just like 00:14:23.840 --> 00:14:28.220 structuring those for basically for both 00:14:28.220 --> 00:14:29.960 avoiding errors and making them source 00:14:29.960 --> 00:14:31.040 code control friendly. 00:14:31.040 --> 00:14:32.240 What's the story there? 00:14:32.240 --> 00:14:34.240 It started with sort of this being a 00:14:34.240 --> 00:14:34.980 pet peeve of mine. 00:14:34.980 --> 00:14:38.800 Like if you use lists or any of the other 00:14:38.800 --> 00:14:40.680 built-in collection classes like a 00:14:40.680 --> 00:14:42.820 dictionary or set, and you're trying to 00:14:42.820 --> 00:14:45.060 define a constant in your code, like, 00:14:45.140 --> 00:14:47.000 let's say, you know, a list of names 00:14:47.000 --> 00:14:50.040 or a set of some other objects. 00:14:50.040 --> 00:14:52.060 If those get too long and they don't 00:14:52.060 --> 00:14:54.140 fit into a line, like usually, you 00:14:54.140 --> 00:14:55.740 know, according to pep8, we're spacing 00:14:55.740 --> 00:14:57.320 them out and we're kind of spreading 00:14:57.320 --> 00:14:58.480 them out across line breaks. 00:14:58.480 --> 00:15:01.580 Now, when you do that, this usually 00:15:01.580 --> 00:15:02.320 looks pretty good. 00:15:02.320 --> 00:15:04.440 But then when you add an element to 00:15:04.440 --> 00:15:06.200 the end of the list, you've got to 00:15:06.200 --> 00:15:08.580 make sure you have your trailing 00:15:08.580 --> 00:15:11.460 comma right in that list, because if 00:15:11.460 --> 00:15:13.720 there's no trailing comma, then and 00:15:13.720 --> 00:15:14.780 you're working with strings, for 00:15:14.780 --> 00:15:17.100 example, cpython, the interpreter or 00:15:17.100 --> 00:15:18.840 the parser is actually going to mash 00:15:18.840 --> 00:15:20.720 two consecutive strings together into 00:15:20.720 --> 00:15:21.140 one. 00:15:21.140 --> 00:15:22.680 So you're going to end up with a 00:15:22.680 --> 00:15:23.600 completely different value. 00:15:23.600 --> 00:15:25.340 And it's not a it's not a interpreter 00:15:25.340 --> 00:15:27.300 error or parser error or syntax error. 00:15:27.300 --> 00:15:29.420 But this you actually get the wrong 00:15:29.420 --> 00:15:29.780 output. 00:15:29.780 --> 00:15:33.060 And so this if that makes sense so far. 00:15:33.060 --> 00:15:35.540 So if the first if you had a list of 00:15:35.540 --> 00:15:39.120 four for names, name one, two, three, 00:15:39.120 --> 00:15:40.400 and four, and you forget the comma 00:15:40.400 --> 00:15:41.960 because you added a new line, but you 00:15:41.960 --> 00:15:43.420 forgot the comma, it's what's in the 00:15:43.420 --> 00:15:45.860 list is name one, name two, name three 00:15:45.860 --> 00:15:47.780 and four as one string, like as if you 00:15:47.780 --> 00:15:48.860 would put a plus there. 00:15:48.860 --> 00:15:50.600 And that drives me crazy about Python. 00:15:50.600 --> 00:15:52.720 Like, I understand, OK, there's a few 00:15:52.720 --> 00:15:55.480 conveniences, but the ability to 00:15:55.480 --> 00:15:57.720 introduce bugs by having two string 00:15:57.720 --> 00:15:59.000 variables next to each other and 00:15:59.000 --> 00:16:01.480 forgetting a comma or something is 00:16:01.480 --> 00:16:02.680 really frustrating. 00:16:02.680 --> 00:16:05.480 It is totally frustrating. 00:16:05.480 --> 00:16:05.820 Yeah. 00:16:05.820 --> 00:16:08.380 And so this is something that I saw come 00:16:08.380 --> 00:16:09.380 up in code reviews. 00:16:09.380 --> 00:16:11.480 you know, as I was, we were at the 00:16:11.480 --> 00:16:14.340 time like onboarding two new developers 00:16:14.340 --> 00:16:16.620 and this actually came up in the code 00:16:16.620 --> 00:16:17.980 review and we're like, what's going on? 00:16:17.980 --> 00:16:19.140 Like, I hate this language, right? 00:16:19.140 --> 00:16:20.240 Like it was one of these things where 00:16:20.240 --> 00:16:21.980 you run into it and you're like, well, 00:16:21.980 --> 00:16:22.960 why did this just happen? 00:16:22.960 --> 00:16:25.500 And it's like a really nasty error or 00:16:25.500 --> 00:16:26.800 bug that you can introduce into your 00:16:26.800 --> 00:16:27.220 programs. 00:16:27.220 --> 00:16:29.280 And so basically we came up with this 00:16:29.280 --> 00:16:31.020 rule of like just ending every single 00:16:31.020 --> 00:16:32.840 item with a comma because you can in 00:16:32.840 --> 00:16:35.000 Python, you can actually have a 00:16:35.000 --> 00:16:37.900 trailing comma, even in the last and 00:16:37.900 --> 00:16:40.260 the final item in one of these 00:16:40.260 --> 00:16:41.220 collection constants. 00:16:41.220 --> 00:16:41.680 Right. 00:16:41.680 --> 00:16:43.700 The dictionary, the list, whatever, 00:16:43.700 --> 00:16:43.980 right. 00:16:43.980 --> 00:16:45.480 It can always have that comma there. 00:16:45.480 --> 00:16:48.620 The other benefit is if you don't put 00:16:48.620 --> 00:16:50.640 the trailing comma and you're going to 00:16:50.640 --> 00:16:53.380 create new items in that list and you 00:16:53.380 --> 00:16:55.300 look at a diff in source control, it 00:16:55.300 --> 00:16:57.020 looks like the previous item has 00:16:57.020 --> 00:16:58.440 changed as well because that line 00:16:58.440 --> 00:17:00.700 changed with a comma, whereas it only 00:17:00.700 --> 00:17:01.940 changed so you could extend it. 00:17:02.000 --> 00:17:03.440 But if you always put the comma 00:17:03.440 --> 00:17:04.880 there, like literally the lines that 00:17:04.880 --> 00:17:06.380 changed are the lines that changed. 00:17:06.380 --> 00:17:06.980 Yeah, that's right. 00:17:06.980 --> 00:17:09.040 You can keep your your diffs, your 00:17:09.040 --> 00:17:10.400 get diffs nice and clean. 00:17:10.400 --> 00:17:12.240 And I mean, you know, I don't know, 00:17:12.240 --> 00:17:13.520 like this probably makes us sound like 00:17:13.520 --> 00:17:14.360 super nitpicky. 00:17:14.360 --> 00:17:15.820 You know, if you're like, oh, you're 00:17:15.820 --> 00:17:17.500 you're like the senior developer 00:17:17.500 --> 00:17:19.120 reviewing someone else's code, you're 00:17:19.120 --> 00:17:20.180 pointing out stuff like that. 00:17:20.180 --> 00:17:22.080 But honestly, I think a lot of times 00:17:22.080 --> 00:17:23.100 it's a little things, right? 00:17:23.100 --> 00:17:24.740 Like if you see like it's a little 00:17:24.740 --> 00:17:26.600 bit hard to talk about this on, I 00:17:26.600 --> 00:17:28.040 guess, on a podcast where we can show 00:17:28.040 --> 00:17:28.880 people code examples. 00:17:28.880 --> 00:17:30.440 But if you see this in front of you, 00:17:31.040 --> 00:17:32.160 usually people go like, oh, yeah, 00:17:32.160 --> 00:17:32.680 that makes sense. 00:17:32.680 --> 00:17:33.840 I'm just going to start doing that 00:17:33.840 --> 00:17:36.140 because you can just remove that 00:17:36.140 --> 00:17:38.100 class of errors or that potential 00:17:38.100 --> 00:17:39.340 for errors there. 00:17:39.340 --> 00:17:40.640 You can just remove that completely 00:17:40.640 --> 00:17:42.860 just by making one tiny, tiny, 00:17:42.860 --> 00:17:44.900 small change to your coding habits 00:17:44.900 --> 00:17:46.220 or how you write your code. 00:17:46.220 --> 00:17:47.680 It's super simple to do and 00:17:47.680 --> 00:17:48.780 understand how it works is great. 00:17:48.780 --> 00:17:50.400 The other place that that's really 00:17:50.400 --> 00:17:52.000 helpful is for code generation. 00:17:52.000 --> 00:17:54.000 So imagine you've got like a cookie 00:17:54.000 --> 00:17:56.240 cutter template and you're cookie. 00:17:56.440 --> 00:17:58.380 you enter some values and that's 00:17:58.380 --> 00:17:59.720 powered by Jinja, too. 00:17:59.720 --> 00:18:02.360 So you put some very like give it a 00:18:02.360 --> 00:18:03.620 list and it'll generate like it could 00:18:03.620 --> 00:18:04.860 generate a bunch of code that's going 00:18:04.860 --> 00:18:06.060 to generate your starter project. 00:18:06.060 --> 00:18:08.180 And because you can trail everything 00:18:08.180 --> 00:18:09.480 with a comma, you don't need some weird 00:18:09.480 --> 00:18:11.560 if case to like filter out the last 00:18:11.560 --> 00:18:12.800 comma and just throw that puppy in 00:18:12.800 --> 00:18:13.500 there and it's all good. 00:18:13.500 --> 00:18:14.220 Oh, that's nice. 00:18:14.220 --> 00:18:15.060 Yeah, I see. 00:18:15.060 --> 00:18:15.680 That would make sense. 00:18:15.680 --> 00:18:15.860 Yeah. 00:18:17.860 --> 00:18:19.700 This portion of Talk Python To Me is 00:18:19.700 --> 00:18:20.980 brought to you by Linode. 00:18:20.980 --> 00:18:22.680 Are you looking for bulletproof 00:18:22.680 --> 00:18:23.880 hosting that's fast, simple 00:18:23.880 --> 00:18:25.020 and incredibly affordable? 00:18:25.020 --> 00:18:26.960 Look past that bookstore and check 00:18:26.960 --> 00:18:29.040 out Linode at talkpython.fm 00:18:29.040 --> 00:18:31.180 slash Linode, L-I-N-O-D-E. 00:18:31.180 --> 00:18:33.360 Plans start at just $5 a month for 00:18:33.360 --> 00:18:35.520 a dedicated server with a gig of RAM. 00:18:35.520 --> 00:18:37.540 They have 10 data centers across the 00:18:37.540 --> 00:18:37.720 globe. 00:18:37.720 --> 00:18:38.960 So no matter where you are, 00:18:38.960 --> 00:18:40.440 there's a data center near you. 00:18:40.440 --> 00:18:41.800 Whether you want to run your Python 00:18:41.800 --> 00:18:43.480 web app, host a private Git server 00:18:43.480 --> 00:18:45.480 or a file server, you'll get native 00:18:45.480 --> 00:18:47.460 SSDs on all machines, a newly 00:18:47.460 --> 00:18:49.880 upgraded 200 gigabit network and 00:18:49.880 --> 00:18:51.620 24-7 friendly support, even on 00:18:51.620 --> 00:18:53.180 holidays and a seven day money 00:18:53.180 --> 00:18:53.820 back guarantee. 00:18:53.820 --> 00:18:55.940 Want a dedicated server for free 00:18:55.940 --> 00:18:57.260 for the next four months? 00:18:57.260 --> 00:18:59.840 Use the coupon code Python17 at 00:18:59.840 --> 00:19:01.600 talkpython.fm/Linode. 00:19:01.600 --> 00:19:05.760 Let's move on to sort of a more 00:19:05.760 --> 00:19:08.360 protective, defensive way of coding 00:19:08.360 --> 00:19:11.460 by covering our assets with asserts. 00:19:11.460 --> 00:19:14.920 Yeah, the assert statement. 00:19:14.920 --> 00:19:15.260 Yeah. 00:19:15.260 --> 00:19:16.440 So you talked about the assert 00:19:16.440 --> 00:19:18.180 statement, which I don't see being used 00:19:18.180 --> 00:19:20.280 all that much in the code that I run 00:19:20.280 --> 00:19:20.660 across. 00:19:20.660 --> 00:19:22.020 Maybe it's just what I've been looking 00:19:22.020 --> 00:19:23.500 at, but I don't see it that often. 00:19:23.500 --> 00:19:23.860 Yeah. 00:19:23.860 --> 00:19:25.000 And I think that's a shame. 00:19:25.000 --> 00:19:25.860 I don't know. 00:19:25.860 --> 00:19:27.700 Like I always felt the assert statement 00:19:27.700 --> 00:19:29.940 in Python was really, really useful. 00:19:29.940 --> 00:19:31.900 I feel like it's underutilized. 00:19:31.900 --> 00:19:34.840 It can really help people write while 00:19:34.840 --> 00:19:36.740 making their code easier to debug. 00:19:36.740 --> 00:19:38.540 First and foremost, you know, it's 00:19:38.540 --> 00:19:40.780 like a defensive programming technique. 00:19:41.020 --> 00:19:43.680 And basically what an assert statement does, 00:19:43.680 --> 00:19:47.160 it's like a shorthand for testing a condition. 00:19:47.160 --> 00:19:50.160 And then if the condition is false, it will 00:19:50.160 --> 00:19:51.860 automatically raise an exception. 00:19:51.860 --> 00:19:54.260 It will just throw an assertion error. 00:19:54.260 --> 00:19:56.540 So you can use assert statements in your code 00:19:56.540 --> 00:19:58.320 just to quickly test conditions. 00:19:58.320 --> 00:20:00.960 If you don't want to write, you know, like a 00:20:00.960 --> 00:20:03.040 longer if statement and really, you know, maybe 00:20:03.040 --> 00:20:04.640 define a custom exception or anything like 00:20:04.640 --> 00:20:04.880 that. 00:20:04.880 --> 00:20:06.700 You just want to make sure that, for example, a 00:20:06.700 --> 00:20:08.800 product price, it shouldn't be negative or 00:20:08.800 --> 00:20:10.020 something like that, where you don't really 00:20:10.020 --> 00:20:12.040 expect this to happen, but you kind of want 00:20:12.040 --> 00:20:14.560 to make sure that it can never actually really 00:20:14.560 --> 00:20:16.380 happen in production because crazy things 00:20:16.380 --> 00:20:17.540 sometimes happen in production. 00:20:17.540 --> 00:20:21.460 Then this is just a great little tool or little 00:20:21.460 --> 00:20:23.600 feature in Python that you can use. 00:20:23.740 --> 00:20:25.480 Yeah. And I really like the little examples 00:20:25.480 --> 00:20:25.980 that you give. 00:20:25.980 --> 00:20:28.000 So like when you introduce assertions, you talk 00:20:28.000 --> 00:20:30.780 about like, let's imagine you have a store, say 00:20:30.780 --> 00:20:32.580 for buying online classes or something, and you 00:20:32.580 --> 00:20:34.520 want to set up a discount coupon type of 00:20:34.520 --> 00:20:34.900 mechanism. 00:20:34.900 --> 00:20:37.140 And so you might assert that after applying the 00:20:37.140 --> 00:20:40.820 discount, the price is no less than zero and no 00:20:40.820 --> 00:20:43.400 more than the actual maximum price. 00:20:43.400 --> 00:20:45.860 So you don't get like a negative, negative coupon 00:20:45.860 --> 00:20:46.500 or something. 00:20:46.500 --> 00:20:48.600 Charge them more than if they didn't enter it. 00:20:48.600 --> 00:20:50.000 The worst coupon in the world. 00:20:50.000 --> 00:20:51.940 Please don't put that in. 00:20:53.640 --> 00:20:55.360 Yeah. So that's, those are all these little 00:20:55.360 --> 00:20:56.860 examples that you have in the book are really 00:20:56.860 --> 00:20:59.160 great. And so like asserting after you apply the 00:20:59.160 --> 00:21:02.660 discount code that the price is zero to the full 00:21:02.660 --> 00:21:04.500 price is pretty straightforward. 00:21:04.500 --> 00:21:07.780 So you do talk about some really interesting things 00:21:07.780 --> 00:21:11.580 in here. One is that the idea behind assertions is 00:21:11.580 --> 00:21:14.220 not the same as proper error handling. 00:21:14.220 --> 00:21:16.740 And that these are really meant to handle 00:21:16.740 --> 00:21:20.460 conditions that are like bugs, not just invalid 00:21:20.460 --> 00:21:20.900 input. 00:21:20.900 --> 00:21:23.040 That's right. Yeah. You want to basically use an 00:21:23.040 --> 00:21:26.740 assertion. If you want to inform yourself or fellow 00:21:26.740 --> 00:21:29.660 developers about an unrecoverable error in your 00:21:29.660 --> 00:21:32.320 program. So I like to think of them more as a 00:21:32.320 --> 00:21:35.900 debugging aid rather than just, you know, a glorifier, 00:21:35.900 --> 00:21:38.800 like a fancy or weird way to throw an exception. 00:21:38.800 --> 00:21:41.640 So this is really, you know, your app is probably still 00:21:41.640 --> 00:21:45.040 going to come down crashing, but at least you will know 00:21:45.040 --> 00:21:48.160 exactly what cost your application to crash. 00:21:48.280 --> 00:21:51.160 So it's usually going to make it easier to have your 00:21:51.160 --> 00:21:54.200 application, to have it fail fast, right? 00:21:54.200 --> 00:21:56.940 When it hits that, that condition that it should not, or 00:21:56.940 --> 00:22:00.340 when it goes into a state that it should not be in rather than 00:22:00.340 --> 00:22:01.400 having that carry on. 00:22:01.400 --> 00:22:03.900 And then at a later time, you know, cause trouble further down 00:22:03.900 --> 00:22:06.420 the road. And so using an assert statement or using multiple 00:22:06.420 --> 00:22:09.400 assert statements, that's a great way to just have these little 00:22:09.400 --> 00:22:13.740 checkpoints in your code that you can just sprinkle around these 00:22:13.740 --> 00:22:17.600 little self checks and they can really save you a ton of time 00:22:17.600 --> 00:22:19.800 because they give you all the context you need. 00:22:19.800 --> 00:22:24.140 They make it easier for you to have that context to debug your 00:22:24.140 --> 00:22:26.520 programs because of course, nothing is a silver bullet here. 00:22:26.520 --> 00:22:27.500 So yeah, sure. 00:22:27.500 --> 00:22:30.860 But I do think it's good to have, like you said, that context, 00:22:30.860 --> 00:22:34.100 because a lot of times maybe the website would start crashing 00:22:34.100 --> 00:22:37.540 because Stripe is rejecting the price that you're trying to 00:22:37.540 --> 00:22:39.020 charge when the price is negative. 00:22:39.020 --> 00:22:40.700 And you're like, what is going on here? 00:22:40.700 --> 00:22:41.960 Why is this happening? 00:22:41.960 --> 00:22:42.260 Right. 00:22:42.260 --> 00:22:45.200 Whereas if you had an assertion that said, well, like when we 00:22:45.200 --> 00:22:46.980 applied the discount code, the price went negative. 00:22:46.980 --> 00:22:48.560 Like, oh, I see. 00:22:48.560 --> 00:22:49.980 I know what's going on here. 00:22:49.980 --> 00:22:52.620 So it's really nice. 00:22:52.620 --> 00:22:58.120 A final warning that you had in here is you should not use 00:22:58.120 --> 00:23:01.080 assertions for regular checks, right? 00:23:01.120 --> 00:23:04.620 Like if you ask a person to enter a number between zero and 00:23:04.620 --> 00:23:07.620 10 and they enter 11, you shouldn't like assert that that's 00:23:07.620 --> 00:23:08.780 between zero to 10, right? 00:23:08.780 --> 00:23:14.140 Because they can be turned off the dunder debug setting that you 00:23:14.140 --> 00:23:15.040 talk about. 00:23:15.040 --> 00:23:19.260 And also they're, they don't, don't tell you anything about it 00:23:19.260 --> 00:23:21.200 from a perspective of the exception, right? 00:23:21.200 --> 00:23:25.140 It's always an assertion error, not like a negative number custom 00:23:25.140 --> 00:23:26.480 exception thing you made or something. 00:23:26.480 --> 00:23:26.760 Yeah. 00:23:26.760 --> 00:23:30.720 You can add a message to the assertion that will also be part of 00:23:30.720 --> 00:23:32.680 the exception stack trace. 00:23:32.680 --> 00:23:36.480 But, but yeah, like you said, it's, it's pretty dangerous to use 00:23:36.480 --> 00:23:40.680 assertions for actually handling conditions or checking for 00:23:40.680 --> 00:23:43.480 conditions that you expect to happen as part of the normal program 00:23:43.480 --> 00:23:43.840 flow. 00:23:43.840 --> 00:23:47.060 So for example, if you do your user validation with an assert 00:23:47.060 --> 00:23:51.100 statement, you know, if you go assert user is admin or something 00:23:51.100 --> 00:23:53.160 like that, well, that's going to work great. 00:23:53.160 --> 00:23:56.380 But as soon as these assertions are turned off and they can be 00:23:56.380 --> 00:24:01.780 globally disabled at the interpreter level, then all of a sudden, you know, 00:24:01.780 --> 00:24:04.580 everyone can log into your app and do all kinds of crazy things because 00:24:04.580 --> 00:24:05.960 all of a sudden everyone is an admin. 00:24:05.960 --> 00:24:07.340 And so you don't want to do that. 00:24:07.340 --> 00:24:08.240 Yeah, that's for sure. 00:24:08.240 --> 00:24:09.540 Yeah. 00:24:09.540 --> 00:24:12.800 You would basically be able to pass a flag that turns off all air 00:24:12.800 --> 00:24:14.560 handling and preconditioned checking. 00:24:14.560 --> 00:24:16.340 That might be bad. 00:24:16.340 --> 00:24:19.520 Do you know why they are statements and not functions? 00:24:19.520 --> 00:24:21.580 I remember reading about that. 00:24:21.580 --> 00:24:24.660 I hope I didn't actually mention this in the book and now I forgot about it. 00:24:24.720 --> 00:24:25.480 I don't think you did. 00:24:25.480 --> 00:24:29.040 It seems to me like maybe one of the reasons is if you do turn them 00:24:29.040 --> 00:24:32.840 off, they can like literally vanish from the code and not just become 00:24:32.840 --> 00:24:34.240 operations that don't do anything. 00:24:34.240 --> 00:24:36.440 So maybe they're easier to like factor out. 00:24:36.440 --> 00:24:39.320 I actually have no idea, but it drives me crazy. 00:24:39.320 --> 00:24:43.780 Like there's like weird conditions about the tuples versus parameters and 00:24:43.780 --> 00:24:48.260 all sorts of funkiness because they're not just like actual calls, 00:24:48.260 --> 00:24:48.880 function calls. 00:24:48.880 --> 00:24:49.380 That's right. 00:24:49.380 --> 00:24:53.900 It's very easy to write assertion statements that never fail because you 00:24:53.900 --> 00:24:58.620 would somehow intuitively think this feels more like a function call, 00:24:58.620 --> 00:25:01.760 sort of like the print statement versus the print function. 00:25:01.760 --> 00:25:07.060 But if you write a syntax or if you use this like a function and you put 00:25:07.060 --> 00:25:11.720 parentheses around it, Python can actually interpret it as this as a tuple. 00:25:11.720 --> 00:25:16.020 So it's like the assert statement plus a tuple expression. 00:25:17.020 --> 00:25:21.020 This will always be so this will also be true or truthy. 00:25:21.020 --> 00:25:25.920 And so, yeah, you can you can shoot yourself in the foot that way. 00:25:25.920 --> 00:25:29.420 But I think this is now actually a warning in Python 3. 00:25:29.420 --> 00:25:29.900 Yeah. 00:25:29.900 --> 00:25:30.140 Yeah. 00:25:30.140 --> 00:25:32.080 You do get a warning in at least 3.6. 00:25:32.080 --> 00:25:33.040 I can tell you that for sure. 00:25:33.040 --> 00:25:33.720 So that's good. 00:25:33.720 --> 00:25:34.020 Yeah. 00:25:34.020 --> 00:25:34.360 Yeah. 00:25:34.700 --> 00:25:36.980 But I'd rather have just the language, actually, you know, 00:25:36.980 --> 00:25:40.860 just not let that be possible in the first place. 00:25:40.860 --> 00:25:41.480 All right. 00:25:41.480 --> 00:25:42.880 So let's move on to the next one. 00:25:42.880 --> 00:25:45.060 The shocking truth about string formatting. 00:25:45.060 --> 00:25:47.200 It's not very Zen-like, is it? 00:25:47.200 --> 00:25:47.520 Yeah. 00:25:47.520 --> 00:25:49.160 No, that's true. 00:25:49.160 --> 00:25:53.980 I mean, this is one of the realizations I had when the format strings or F 00:25:53.980 --> 00:25:56.200 strings landed in Python 3.6. 00:25:56.580 --> 00:25:57.980 I was like, hold on a minute. 00:25:57.980 --> 00:26:01.880 Like, there's like four different ways to do string formatting in Python now. 00:26:01.880 --> 00:26:03.640 And variations on each four of those. 00:26:03.640 --> 00:26:07.620 So which one should I actually use? 00:26:07.620 --> 00:26:11.660 And it seemed to go against the Zen of Python as well. 00:26:11.660 --> 00:26:16.300 And, you know, I guess it's one of these things where, well, languages, they evolve over time 00:26:16.300 --> 00:26:20.740 and we can't just throw out, you know, all of the legacy code that we have. 00:26:20.740 --> 00:26:23.700 So it's like a trade-off that we need to make or people need to make. 00:26:23.900 --> 00:26:25.920 But still, I just thought it was interesting. 00:26:25.920 --> 00:26:28.960 And yeah, so let's chat about that. 00:26:28.960 --> 00:26:29.620 Yeah, for sure. 00:26:29.620 --> 00:26:36.880 So we've got the old style formatting, the like string with a percent, a format character. 00:26:36.880 --> 00:26:39.700 So percent S, percent D, and so on, percent F. 00:26:39.700 --> 00:26:44.900 Then mod the values or a tuple of the values to be inserted. 00:26:44.900 --> 00:26:49.780 And that's kind of more or less not the way these days, right? 00:26:49.780 --> 00:26:50.200 Yeah. 00:26:50.200 --> 00:26:53.600 I mean, it's called old style formatting for a reason, I guess. 00:26:53.600 --> 00:26:59.400 But yeah, so we have a newer way of doing string formatting. 00:26:59.400 --> 00:27:04.500 And it's called, it's referred to as new style string formatting using the string dot format function. 00:27:04.500 --> 00:27:08.720 But it's not actually the newest style, but it's the middle age. 00:27:08.720 --> 00:27:11.040 And the old style isn't actually... 00:27:11.040 --> 00:27:12.080 It's not deprecated, yeah. 00:27:12.080 --> 00:27:13.120 It's not going to go away, right? 00:27:13.200 --> 00:27:21.000 So I guess it's just a hint that we got from the CPython team that, you know, really you should be using... 00:27:21.000 --> 00:27:22.900 Maybe you shouldn't be using the old style of string formatting. 00:27:22.900 --> 00:27:25.340 On the other hand, it is kind of nice to use. 00:27:25.340 --> 00:27:25.860 Yeah. 00:27:26.120 --> 00:27:30.000 And it's, you know, the new style is still in Python 2.7. 00:27:30.000 --> 00:27:36.220 So new style would be like, hello, curly, curly, all that in quotes, dot format name or something like that. 00:27:36.220 --> 00:27:38.100 And that's pretty standard. 00:27:38.100 --> 00:27:39.040 That's really nice. 00:27:39.040 --> 00:27:47.400 Takes a lot of sort of its own formatting mini language to convert the values like numbers to digit grouping and things like that. 00:27:47.840 --> 00:27:52.420 And then we've got the f-strings, which are the new hotness in 3.6, right? 00:27:52.420 --> 00:27:55.160 Yeah, the f-strings are just awesome. 00:27:55.160 --> 00:27:56.800 They were added in Python 3.6. 00:27:56.800 --> 00:27:58.540 And I think it's a really, really great feature. 00:27:58.540 --> 00:28:01.360 The f-strings are also called formatted string literals. 00:28:01.360 --> 00:28:04.560 And people also refer to this as string interpolation. 00:28:04.560 --> 00:28:08.300 So really what this means is it's basically a new type of string. 00:28:08.300 --> 00:28:11.720 So you just put a lowercase f in front of your string. 00:28:12.440 --> 00:28:20.660 And then you can use curly braces to just have a Python expressions right in your string. 00:28:20.660 --> 00:28:30.400 And when Python evaluates that string, it's actually going to evaluate those expressions, convert them to a string, and then merge them with the surrounding pieces or parts of that string. 00:28:30.400 --> 00:28:37.520 So this is a really, really nice and concise way to define strings in Python that are dynamic. 00:28:37.520 --> 00:28:41.840 And it does the same job than all of the other formatting tools that we talked about or formatting styles. 00:28:42.040 --> 00:28:46.920 But I find this to be very readable and just very, very nice to work with. 00:28:46.920 --> 00:28:48.180 Yeah, I really like it too. 00:28:48.180 --> 00:28:50.800 The more I use it, the more I really want to use it everywhere. 00:28:50.800 --> 00:28:51.640 It's great. 00:28:51.640 --> 00:28:57.180 And so you would say F quote and then have a regular text and then curly curly. 00:28:57.180 --> 00:29:00.080 Then, like you said, you put these expressions and they don't. 00:29:00.080 --> 00:29:08.760 It looks very similar to the dictionary version or the keyword value version of the old format or the new old format or middle-aged format. 00:29:09.020 --> 00:29:10.960 But you can do things that are unexpected. 00:29:10.960 --> 00:29:14.420 Like you could actually call functions inside there. 00:29:14.420 --> 00:29:16.540 You can add up things. 00:29:16.540 --> 00:29:27.300 You can, what I didn't realize is you can actually put format descriptors like some variable colon hash X for hexadecimal representation. 00:29:27.300 --> 00:29:28.720 And that's pretty cool. 00:29:28.900 --> 00:29:29.480 It's pretty neat. 00:29:29.480 --> 00:29:35.140 And I think it's also nice and readable because you just have all of the context you want. 00:29:35.140 --> 00:29:43.360 Like one of the challenges I've felt with, you know, at least old style string formatting format is that a lot of times you have to jump back and forth. 00:29:43.360 --> 00:29:52.780 And then, you know, if you have a complicated format string, you have to actually count out like, okay, this percent S, a placeholder, it refers to this other variable. 00:29:52.780 --> 00:29:57.920 And you just have to do all of that, that mental gymnastics to figure out what's actually going on. 00:29:57.920 --> 00:30:02.700 And with f-strings, well, you see it right in front of you and it's kind of nice. 00:30:02.700 --> 00:30:03.000 Yeah. 00:30:03.000 --> 00:30:04.640 It eliminates a whole class of bugs. 00:30:04.640 --> 00:30:13.840 Like it's totally possible to have too few arguments in like a format expression or too many arguments or get them in the wrong order. 00:30:13.840 --> 00:30:18.080 But when the actual variable goes in the spot, like that's what's in the spot, right? 00:30:18.080 --> 00:30:19.160 There's no more debate in it. 00:30:19.160 --> 00:30:19.340 Yeah. 00:30:19.340 --> 00:30:27.340 I guess the one thing that is kind of nice sometimes is in the string, you have to repeat something that's like sort of an expression that got evaluated. 00:30:27.340 --> 00:30:28.920 Like that might be in the middle. 00:30:28.920 --> 00:30:33.460 And so I'm going to propose some nomenclature here and we'll see if the world will take it. 00:30:33.460 --> 00:30:34.120 I don't know. 00:30:34.120 --> 00:30:37.120 So let's call the old style. 00:30:37.120 --> 00:30:38.500 Old style is finer. 00:30:38.500 --> 00:30:40.140 It could be legacy style formatting. 00:30:40.140 --> 00:30:42.040 I think that's even a better word for it. 00:30:42.040 --> 00:30:45.380 The new style, what should we call that? 00:30:45.380 --> 00:30:45.860 What do you think? 00:30:45.860 --> 00:30:49.400 The traditional string formatting style. 00:30:49.400 --> 00:30:52.920 And then the interpolation, we could call that the new style. 00:30:52.920 --> 00:30:54.380 The new style. 00:30:54.380 --> 00:30:54.540 Yeah. 00:30:54.540 --> 00:30:55.680 Let's do that. 00:30:55.680 --> 00:31:00.640 Let's go and submit a pull request on the Python, CPython docs. 00:31:00.640 --> 00:31:01.200 Exactly. 00:31:01.200 --> 00:31:02.660 Let's do a PEP to change the naming. 00:31:02.660 --> 00:31:03.900 Exactly. 00:31:04.660 --> 00:31:05.100 Exactly. 00:31:05.100 --> 00:31:06.640 And so really quick. 00:31:06.640 --> 00:31:12.900 The last one is one that I really hadn't played with, which is it's sort of the little Bobby tables equivalent of string. 00:31:13.640 --> 00:31:16.800 So it's something called string templates. 00:31:16.800 --> 00:31:21.660 And it's really good for when you're like taking an untrusted input and jamming it into a string format. 00:31:21.660 --> 00:31:24.900 Yeah, this is great when you're dealing with user input. 00:31:24.900 --> 00:31:30.920 You know, when you have something else that comes in externally where users can actually define those templates. 00:31:30.920 --> 00:31:40.400 Because the problem is if you just feed that into one of the other formatting techniques or methods, people can actually execute code in your interpreter environment. 00:31:40.720 --> 00:31:47.720 So there's a way to reach out and look at global variables. 00:31:47.720 --> 00:31:51.720 I mean, I'm in Ronaker's blog where he demonstrated that technique. 00:31:51.720 --> 00:32:06.180 And basically you can go in and there's a way to reach out from a format string and to reach into the Dunder globals dictionary and just to look up any variable in the global variable environment. 00:32:06.340 --> 00:32:12.840 So, you know, if you have your secret API key in there and this is a web app, then, well, bye bye API key. 00:32:12.840 --> 00:32:15.480 It's just going to, you know, people can leak it out. 00:32:15.480 --> 00:32:16.120 What's my name? 00:32:16.120 --> 00:32:19.560 My name is global square bracket AWS secret key. 00:32:19.560 --> 00:32:21.300 Oh, look, there it is. 00:32:21.300 --> 00:32:22.460 Yeah, that's bad. 00:32:22.460 --> 00:32:22.740 Yeah. 00:32:22.740 --> 00:32:23.080 Okay. 00:32:23.080 --> 00:32:23.300 Yeah. 00:32:23.300 --> 00:32:24.600 So you can use this template thing. 00:32:24.600 --> 00:32:26.940 And so the template strings, they prevent that. 00:32:26.940 --> 00:32:27.480 Yeah, nice. 00:32:27.480 --> 00:32:30.620 They're kind of like parametrize queries in SQL expressions. 00:32:30.620 --> 00:32:32.020 Like they don't really get evaluated. 00:32:32.620 --> 00:32:38.780 They just get put in there as raw strings, but they kind of signal that this part is input and it doesn't run. 00:32:38.780 --> 00:32:41.000 And this, it just goes here as text. 00:32:41.000 --> 00:32:45.560 This portion of Talk Python To Me has been brought to you by Rollbar. 00:32:45.560 --> 00:32:49.220 One of the frustrating things about being a developer is dealing with errors. 00:32:49.220 --> 00:32:58.240 Relying on users to report errors, digging through log files, trying to debug issues, or getting millions of alerts just flooding your inbox and ruining your day. 00:32:58.700 --> 00:33:05.000 With Rollbar's full stack error monitoring, you get the context, insight, and control you need to find and fix bugs faster. 00:33:05.000 --> 00:33:08.960 Adding Rollbar to your Python app is as easy as pip install Rollbar. 00:33:08.960 --> 00:33:13.200 You can start tracking production errors and deployments in eight minutes or less. 00:33:13.200 --> 00:33:17.400 Are you considering self-hosting tools for security or compliance reasons? 00:33:17.400 --> 00:33:20.960 Then you should really check out Rollbar's compliant SaaS option. 00:33:21.000 --> 00:33:30.340 Get advanced security features and meet compliance without the hassle of self-hosting, including HIPAA, ISO 27001, Privacy Shield, and more. 00:33:30.340 --> 00:33:31.720 They'd love to give you a demo. 00:33:31.720 --> 00:33:33.420 Give Rollbar a try today. 00:33:33.420 --> 00:33:37.100 Go to talkpython.fm/Rollbar and check them out. 00:33:37.860 --> 00:33:41.480 So the next one that you talked about is exceptions. 00:33:41.480 --> 00:33:44.280 And there's all sorts of stuff around exceptions. 00:33:44.280 --> 00:33:53.980 I mean, there's the whole embracing the look before you leap, rather disregarding the look before you leap style from C and embracing that it's easier to ask for forgiveness than permission. 00:33:53.980 --> 00:34:00.080 And just really using exceptions as, like, for exceptional cases, right? 00:34:00.080 --> 00:34:07.380 But then there's also making sense of the consuming the APIs that have been really embracing that format. 00:34:07.380 --> 00:34:15.000 So Crete, your recommendation is to define your own exception classes to make your code more readable, self-documenting, and so on, right? 00:34:15.000 --> 00:34:17.900 Under some circumstances, I think that makes a lot of sense. 00:34:17.900 --> 00:34:23.740 I feel like a lot of times you're totally fine if you just, let's say, raise a value error or a key error. 00:34:23.740 --> 00:34:33.680 If it's just perfectly clear, you know, if you're working with a small function and this is not some perfectly polished library that you're releasing to the world, you know, just go ahead and raise a value error. 00:34:33.680 --> 00:34:36.140 Don't bother with defining your own exception hierarchy. 00:34:36.140 --> 00:34:51.720 But I think as soon as you have a larger piece of code that you want to share, either across multiple applications or just, you know, kind of have it nicely served in a well-defined package where it's its own package, its own module, then I think it makes sense. 00:34:51.720 --> 00:34:52.760 What do you think about this? 00:34:52.760 --> 00:34:57.700 What if you have your rule as if it has a setup dpy, it has its own exception hierarchy? 00:34:57.700 --> 00:34:58.900 I think that makes a lot of sense. 00:34:58.900 --> 00:34:59.140 Yeah. 00:34:59.140 --> 00:35:00.420 I think that's a package. 00:35:00.420 --> 00:35:00.960 That's a good idea. 00:35:00.960 --> 00:35:02.220 People consume it externally. 00:35:02.220 --> 00:35:05.620 Maybe it should be more formalized in this way. 00:35:05.620 --> 00:35:05.780 Yeah. 00:35:05.780 --> 00:35:06.020 Yeah. 00:35:06.020 --> 00:35:07.120 At the very least then. 00:35:07.120 --> 00:35:27.760 And also if you're working in a bigger application, you know, where you have a lot of code, like I don't do this in any little script that I write, but if you have a larger body of code, I feel like these are the things that really make it easier for you also to work with your code in the future, because it's just nicer or it's easier for you to see, you know, what went wrong and where. 00:35:27.760 --> 00:35:31.360 Essentially, a value error can come from many, many places. 00:35:31.360 --> 00:35:42.360 But if it's a password validator exception that you defined, then, well, you know, this has something to do with password validation or, you know, the next person working on your code knows that it has something to do with that. 00:35:42.600 --> 00:35:43.600 Another thing that I think is really nice. 00:35:43.600 --> 00:35:53.800 Another thing that I think is really nice that you talked about is actually having a base exception that defines, like, these are all the errors that come out of this particular package. 00:35:53.800 --> 00:35:55.560 So that makes me crazy. 00:35:55.680 --> 00:35:58.160 Sometimes I'll be like handling errors out of different packages. 00:35:58.160 --> 00:36:00.200 I'm like, what is this thing throwing? 00:36:00.200 --> 00:36:01.680 Is it throwing one of its own errors? 00:36:01.680 --> 00:36:04.880 Is it throwing like a system socket error? 00:36:04.880 --> 00:36:06.240 Like, what is this? 00:36:06.240 --> 00:36:07.960 And how do I find a way to catch it? 00:36:07.960 --> 00:36:08.560 You know what I mean? 00:36:08.560 --> 00:36:13.420 It'd be really nice to go, okay, I'm working with the SQLAlchemy library. 00:36:13.420 --> 00:36:18.520 So I'm going to catch, I'm going to start by catching SQLAlchemy errors and like dealing with that. 00:36:18.520 --> 00:36:22.800 And then I'll start to add on special cases of like, oh yeah, this is when the network is down. 00:36:22.800 --> 00:36:25.680 This is when the database doesn't exist or, you know, whatever. 00:36:25.680 --> 00:36:26.440 Yeah, exactly. 00:36:26.440 --> 00:36:31.360 And some people start using value error or something like that, like a built-in exception for that. 00:36:31.360 --> 00:36:35.540 And then just put that information in the exception message. 00:36:35.540 --> 00:36:43.800 And I mean, for debugging purposes, I think that's okay because, well, you're just going to look at the stack trace and you know, sort of know what's what happened. 00:36:43.800 --> 00:36:49.140 But you really don't have the granularity when you're catching these exceptions, right? 00:36:49.140 --> 00:36:56.340 When you have a try except block and like actually exception is part of your structuring the control flow of your program. 00:36:56.340 --> 00:37:01.400 Then that becomes very dangerous because then, well, you kind of have to parse out that string. 00:37:01.400 --> 00:37:03.360 And I don't know, I don't like that. 00:37:03.360 --> 00:37:03.620 Yeah. 00:37:03.620 --> 00:37:11.960 Well, and also if you're trying to say, well, I'm trying to deal with the case when there's a value error, but is it from this library or that library? 00:37:11.960 --> 00:37:13.460 Because that means really different things. 00:37:13.620 --> 00:37:14.580 One is the network is down. 00:37:14.580 --> 00:37:16.180 The other is you don't have permission. 00:37:16.180 --> 00:37:18.460 And I don't really know what to do here, right? 00:37:18.460 --> 00:37:20.080 So you can totally help that. 00:37:20.080 --> 00:37:29.560 And, you know, another thing that I'm not sure people think very much about, but I think would be really helpful is like discovering the solution to some common problems. 00:37:30.120 --> 00:37:43.080 So if it's a generic standard library error and you go search for that on like Google on Stack Overflow, I use Rollbar and Rollbar has this sort of mechanism where you go into the error reporting for your web app. 00:37:43.080 --> 00:37:48.340 And it says here are the common solutions or issues that are found associated with this error. 00:37:48.460 --> 00:37:50.420 But if it's super general, it's like, well, nothing, right? 00:37:50.420 --> 00:37:56.660 But if it's pretty specific errors, like you could probably get help more easily on lots of levels that way. 00:37:56.660 --> 00:37:58.060 I really like your thinking there. 00:37:58.140 --> 00:38:01.080 It's like this whole meta game of programming, right? 00:38:01.080 --> 00:38:05.020 Where you're not just fending on your own, like you're fighting the machine there. 00:38:05.020 --> 00:38:11.700 But a lot of times it's just great if you can punch something into Google and just at least find some other people who have the same problem. 00:38:11.700 --> 00:38:18.860 And yeah, I think it really increases the Google ability of your exceptions if you do that. 00:38:18.860 --> 00:38:19.580 Yeah, absolutely. 00:38:19.580 --> 00:38:20.260 Totally agree. 00:38:20.260 --> 00:38:21.500 All right. 00:38:21.500 --> 00:38:23.160 So let's talk about naming a little bit. 00:38:23.160 --> 00:38:26.860 I know that you've talked about this on your blog and some articles. 00:38:26.860 --> 00:38:29.460 I've talked about this, Brian Okken on Python Bytes. 00:38:29.460 --> 00:38:37.100 There's a special meaning for underscore and double underscores and prefix underscores and suffix underscores in Python. 00:38:37.100 --> 00:38:39.680 And maybe we should just touch on those a little bit. 00:38:39.680 --> 00:38:43.260 There's like five or so that you cover in here, right? 00:38:43.260 --> 00:38:44.420 So many underscores. 00:38:44.420 --> 00:38:46.020 Yeah, Python does love the underscore. 00:38:46.020 --> 00:38:48.760 I'm getting undersource from all these underscores. 00:38:48.760 --> 00:38:55.760 So the first thing that we can start off with is like a semi-private variable, underscore var. 00:38:55.760 --> 00:38:56.440 Yeah. 00:38:56.440 --> 00:38:59.440 So the underscore var is just a naming convention. 00:38:59.440 --> 00:39:06.300 And I like that you called it semi-private because a lot of times when people come from, let's say, a Java or C# background, 00:39:06.580 --> 00:39:09.700 they assume that private really means private in this context. 00:39:09.700 --> 00:39:12.560 Like you cannot, you know, reach in and modify this variable. 00:39:12.560 --> 00:39:17.100 But in Python, if you do underscore var, it's a naming convention. 00:39:17.100 --> 00:39:19.280 You know, it's just something that the community agrees on. 00:39:19.280 --> 00:39:21.900 It's like a hint to the programmer, but it's generally not enforced. 00:39:21.900 --> 00:39:24.100 So that's something you got to keep in mind. 00:39:24.100 --> 00:39:28.440 Like we're all consenting adults or whatever Guido said about that. 00:39:28.440 --> 00:39:28.960 Exactly. 00:39:28.960 --> 00:39:31.040 I've heard him describe it that way as well. 00:39:31.040 --> 00:39:35.720 But then there's the, yeah, but I still don't trust you. 00:39:35.720 --> 00:39:37.420 So I'll put another underscore in front of it. 00:39:37.520 --> 00:39:37.680 Yeah. 00:39:37.680 --> 00:39:45.760 And that's where it gets interesting because that enables or that kicks, that makes the name mangling kick in. 00:39:45.760 --> 00:39:58.420 So if you do a double underscore in front of your variable name, the Python interpreter will actually mangle that name and prepend the name of the surrounding class to that variable. 00:39:58.740 --> 00:40:12.160 So this sort of kind of makes it like a private variable, but not really, because if you do the mangling yourself, you know, if you just do that string concatenation in your head or in your program, you can still reach in and modify that variable. 00:40:12.160 --> 00:40:19.460 So it's really more a mechanism for preventing naming collisions, but not, you know, not a way to implement private variables. 00:40:19.460 --> 00:40:20.840 Not true private. 00:40:20.840 --> 00:40:26.960 I mean, it's not private in the sense that it's private, but there's still really not that much private in all the other languages. 00:40:27.160 --> 00:40:34.620 So if you think of say C#, it has a private protected internal, all these different mechanisms and scoping rules. 00:40:34.620 --> 00:40:39.600 But then on the other hand, you have reflection and you could just go ask for it for the private variables. 00:40:39.600 --> 00:40:45.400 Java has introspection C++ they have private, but you know, how many bytes offset is that? 00:40:45.400 --> 00:40:45.660 Okay. 00:40:45.660 --> 00:40:49.000 We just go to the front of the object and like read that form over. 00:40:49.000 --> 00:40:54.880 And we, I mean, like in all of these languages, there's a backdoor to these privates. 00:40:54.880 --> 00:40:55.620 Right. 00:40:55.620 --> 00:41:00.660 And so I feel like this is really no more or less than that. 00:41:00.660 --> 00:41:06.440 It's just maybe slightly easier if you know the convention, but it certainly screams to you. 00:41:06.440 --> 00:41:07.760 Don't do this. 00:41:07.760 --> 00:41:08.860 Yeah. 00:41:08.860 --> 00:41:12.440 It's like you're, you're digging a moat around your, around your fortress. 00:41:12.440 --> 00:41:18.220 And, you know, of course people can still overcome it and destroy your beautiful programming fortress, 00:41:18.220 --> 00:41:21.380 but you're just making it a little bit harder for people to hurt themselves. 00:41:21.380 --> 00:41:22.060 So yeah. 00:41:22.060 --> 00:41:26.140 I mean, the whole point is like people shouldn't mess with the internal implementation. 00:41:26.140 --> 00:41:28.660 They shouldn't depend on the internal implementation. 00:41:28.660 --> 00:41:31.020 And if they do, they're going to suffer. 00:41:31.020 --> 00:41:34.360 Not you probably unless they fire out, file a bug and you got to deal with it. 00:41:34.480 --> 00:41:34.560 Yeah. 00:41:34.560 --> 00:41:34.780 Yeah. 00:41:34.780 --> 00:41:34.820 Yeah. 00:41:34.820 --> 00:41:35.960 You would hope so. 00:41:35.960 --> 00:41:36.220 Right. 00:41:36.220 --> 00:41:40.020 That it's not you as the maintainer who gets the flack for that. 00:41:40.020 --> 00:41:40.800 Yeah, exactly. 00:41:40.800 --> 00:41:43.580 But I do think like that's kind of far enough. 00:41:43.580 --> 00:41:44.920 I use that every now and then. 00:41:45.040 --> 00:41:49.480 I also use it for when I want clean autocomplete. 00:41:49.480 --> 00:41:53.080 If there's some library that I'm like, I want to give this to somebody. 00:41:53.080 --> 00:41:58.040 I want them to say thing dot and the list of the stuff I want them to work with really clearly. 00:41:58.040 --> 00:42:03.680 I'll put that either the underscore, the double underscore, not so much to make people stay away, 00:42:03.680 --> 00:42:07.280 but to like make the API more discoverable in the tooling. 00:42:07.280 --> 00:42:07.960 Oh, that's nice. 00:42:07.960 --> 00:42:08.980 That's a good idea. 00:42:08.980 --> 00:42:09.180 Yeah. 00:42:09.180 --> 00:42:11.440 And the double underscore, like it takes it entirely out of the list. 00:42:11.440 --> 00:42:14.800 So I'm kind of like, ah, you know, if it's not going to bother me too much, I might do that. 00:42:14.800 --> 00:42:17.300 But that's one of my motivations. 00:42:17.300 --> 00:42:23.020 I did want to ask you with the single underscore, that means like internal private. 00:42:23.020 --> 00:42:28.460 But do you think that means protected or truly private, like only in the class or classes and 00:42:28.460 --> 00:42:29.080 its derivatives? 00:42:29.080 --> 00:42:34.580 That'll come down to the individual developers and their teams agreement. 00:42:34.580 --> 00:42:41.780 Personally, I use it more like a protected variable, I think, where it's like, yeah, you 00:42:41.780 --> 00:42:44.620 know, if it makes sense to reach in and modify this. 00:42:44.620 --> 00:42:50.200 And we're part of the same, you know, if it's related code, very, very closely related code, 00:42:50.200 --> 00:42:52.360 then I feel like it's okay. 00:42:52.360 --> 00:42:55.940 But it's definitely one of these things where it's it's a it's a slippery slope, right? 00:42:55.940 --> 00:42:57.840 Or it's like, oh, yeah, it'll be fine. 00:42:57.940 --> 00:43:01.220 And it's like one of these famous last word things. 00:43:01.220 --> 00:43:02.360 It's this convention. 00:43:02.360 --> 00:43:04.260 And it's not super explicit, right? 00:43:04.260 --> 00:43:04.980 Like, yeah. 00:43:04.980 --> 00:43:08.460 But I think it's, I think it's good to know about it. 00:43:08.460 --> 00:43:11.300 So just really quickly, maybe touch on the other underscores. 00:43:11.300 --> 00:43:13.520 There's var underscore the suffix. 00:43:13.720 --> 00:43:16.600 Yeah, so that's mostly just used to get around. 00:43:16.600 --> 00:43:23.100 So, you know, you can use a reserved word, like a Python keyword, like class, you can use 00:43:23.100 --> 00:43:24.820 that as a variable name in your programs. 00:43:24.820 --> 00:43:29.680 But a lot of times, it actually makes sense to have a variable name, name class, if you're 00:43:29.680 --> 00:43:31.260 passing in some kind of class to a function. 00:43:31.260 --> 00:43:34.300 Yeah, the place where I've seen it is in Beautiful Soup. 00:43:34.300 --> 00:43:37.100 You can do a find and specify a class keyword. 00:43:37.100 --> 00:43:40.940 And then you say the name of the class you're looking for in the HTML. 00:43:40.940 --> 00:43:42.840 But you can't say class, right? 00:43:42.840 --> 00:43:45.520 So they have class underscore equals as the keyword argument. 00:43:45.520 --> 00:43:46.380 Yeah, there you go. 00:43:46.380 --> 00:43:50.220 And then people sometimes do, they just kind of mangle the name themselves. 00:43:50.220 --> 00:43:53.540 So they maybe call it class with a K or with a Z. 00:43:53.540 --> 00:43:54.900 Yeah, with a Z. 00:43:54.900 --> 00:43:58.340 I actually went and dug through PEP 8. 00:43:58.560 --> 00:44:03.540 And so what people recommend or what like the official recommendation is to just end 00:44:03.540 --> 00:44:06.220 your variable name with an underscore. 00:44:06.220 --> 00:44:11.400 And that disambiguates it and make sure it doesn't conflict or there's no conflict with 00:44:11.400 --> 00:44:13.440 the keyword or the built-in reserved word. 00:44:13.440 --> 00:44:16.980 And I kind of like that because I feel like, yeah, it's pretty clear, pretty easy to remember. 00:44:16.980 --> 00:44:19.640 And we have more underscores that way. 00:44:19.640 --> 00:44:20.400 Isn't that wonderful? 00:44:20.400 --> 00:44:21.200 Yeah, we have more. 00:44:21.200 --> 00:44:25.960 All these languages have ways of dealing with them and none of them are really amazing. 00:44:26.080 --> 00:44:28.660 This seems just totally, totally decent. 00:44:28.660 --> 00:44:34.540 And then we have the Dunder methods, which is really the Python data model magic methods, 00:44:34.540 --> 00:44:36.340 which I know you don't like that term, but. 00:44:36.340 --> 00:44:36.900 Do you like that? 00:44:36.900 --> 00:44:39.760 I was going to ask you, do you like the word magic methods? 00:44:39.760 --> 00:44:41.720 To me, they feel like operators. 00:44:41.720 --> 00:44:42.440 I don't know. 00:44:42.440 --> 00:44:47.240 I don't really like the term either because magic seems like they're inaccessible and 00:44:47.240 --> 00:44:49.580 they're like these internal black box things. 00:44:49.580 --> 00:44:50.380 They're not really right. 00:44:51.140 --> 00:44:56.500 And then the final thing around underscores, because Python loves underscores, is to use 00:44:56.500 --> 00:44:58.640 it as the, I don't care about this variable. 00:44:58.640 --> 00:45:00.240 Don't lint it. 00:45:00.240 --> 00:45:01.900 Don't make me name it. 00:45:01.900 --> 00:45:03.300 I don't care about it. 00:45:03.300 --> 00:45:03.700 Yeah. 00:45:03.700 --> 00:45:08.140 It almost has like a Haskell kind of feel to it where you're like, oh yeah, I'm so cool. 00:45:08.140 --> 00:45:11.940 I'm ignoring all these variables and I'm deconstructing tuples and whatnot. 00:45:13.000 --> 00:45:13.640 Yes, exactly. 00:45:13.640 --> 00:45:14.900 Yeah. 00:45:14.900 --> 00:45:22.100 So if you want to like loop over something like 10 times, you could say for n in range 00:45:22.100 --> 00:45:24.600 one to 11 or zero to 10 or whatever. 00:45:24.600 --> 00:45:29.340 But if you don't care about that n, you know, you might get warnings like that variable is 00:45:29.340 --> 00:45:30.820 not used and whatnot. 00:45:30.820 --> 00:45:33.040 And if you want to be explicit and say, I don't care about the loop variable. 00:45:33.040 --> 00:45:34.080 I just want to do this 10 times. 00:45:34.080 --> 00:45:36.800 Just put an underscore instead of n and everything's good. 00:45:36.800 --> 00:45:38.140 Same thing for like parameters. 00:45:38.140 --> 00:45:38.400 Yeah. 00:45:38.400 --> 00:45:39.040 And methods. 00:45:39.040 --> 00:45:39.280 Yeah. 00:45:39.280 --> 00:45:43.140 The only thing you got to be careful about is when you do that in a Python REPL session 00:45:43.140 --> 00:45:49.600 where the underscore, like a single standalone underscore is usually represents the result 00:45:49.600 --> 00:45:54.300 of the last expression that the interpreter evaluated, which is kind of nice if you're using, 00:45:54.300 --> 00:46:00.180 you know, if you're working with the REPL, but if you redefine it, that can cause all kinds 00:46:00.180 --> 00:46:00.540 of trouble. 00:46:00.540 --> 00:46:05.500 So, you know, that's kind of the one caveat with using the single underscore. 00:46:05.500 --> 00:46:06.320 That's for sure. 00:46:06.320 --> 00:46:09.860 And it's nice because if you type an expression like, oh, geez, I would love to use that as 00:46:09.860 --> 00:46:10.300 a variable. 00:46:10.300 --> 00:46:13.780 You can say variable name equals underscore and then roll on from there. 00:46:13.780 --> 00:46:15.240 That's nice in the REPL. 00:46:15.240 --> 00:46:15.700 Yeah. 00:46:15.700 --> 00:46:16.720 All right. 00:46:16.720 --> 00:46:18.600 So let's move on to data structures. 00:46:18.600 --> 00:46:22.060 And this is like a pretty significant chapter that you talk about. 00:46:22.060 --> 00:46:25.280 And I kind of hinted at this at the opening. 00:46:25.280 --> 00:46:29.700 Like you can come in and find the really basic structures really easily, but there's actually 00:46:29.700 --> 00:46:35.700 a rich set of data structures that are special made for certain circumstances and situations. 00:46:36.240 --> 00:46:37.820 So let's dig into those. 00:46:37.820 --> 00:46:42.000 Maybe, yeah, start with the dictionaries because that's a pretty central thing in Python. 00:46:42.000 --> 00:46:42.500 Yeah. 00:46:42.500 --> 00:46:47.840 It's like the central data structure in definitely, I think, in Python and in, I feel like probably 00:46:47.840 --> 00:46:51.360 in programming in general, it's like just a super versatile tool. 00:46:51.360 --> 00:46:51.560 Yeah. 00:46:51.560 --> 00:46:53.660 And it's not just something you use in Python, right? 00:46:53.660 --> 00:46:58.920 Like the variables and attributes in a class are defined by those. 00:46:59.160 --> 00:47:02.340 You know, the stuff in module, like global variables, all sorts of stuff, right? 00:47:02.340 --> 00:47:07.440 Like it's the structure that stores, that holds the types of Python together, I guess. 00:47:07.440 --> 00:47:10.040 Like the stuff the universe is really made off. 00:47:10.040 --> 00:47:12.760 It's the dark matter of Python. 00:47:14.960 --> 00:47:15.960 I like that. 00:47:15.960 --> 00:47:16.480 Yeah. 00:47:16.480 --> 00:47:21.100 And it's, I mean, it's everywhere, you know, but on the other hand, when we started, you 00:47:21.100 --> 00:47:25.240 know, the last place I worked at, we were interviewing pretty aggressively and by aggressively mean, 00:47:25.240 --> 00:47:29.080 you know, interviewing a lot of people and trying to hire Python developers. 00:47:29.080 --> 00:47:34.200 And so one of the things that came up over and over again in those interviews that was that 00:47:34.200 --> 00:47:38.020 people were really struggling with when you're talking about like basic, like hash table or 00:47:38.020 --> 00:47:43.440 hash map questions, people were like, yeah, I'm not sure if that's available in Python. 00:47:43.440 --> 00:47:49.340 And I don't really know how this concept would work in Python, but at the same time, they knew 00:47:49.340 --> 00:47:50.060 about dictionaries. 00:47:50.060 --> 00:47:52.960 So that was just, I don't know. 00:47:52.960 --> 00:47:56.780 I mean, obviously, you know, I understand where this is coming from and this is not necessarily 00:47:56.780 --> 00:47:57.760 like a terrible sign. 00:47:57.760 --> 00:48:00.060 But on the other hand, I was curious or just confused. 00:48:00.060 --> 00:48:01.280 Like, why, why was this happening? 00:48:01.280 --> 00:48:04.100 I mean, you know, like, why, why is there this disconnect? 00:48:04.100 --> 00:48:10.500 Because in Java, well, if you want like a mapping structure or a dictionary, you know that you're 00:48:10.500 --> 00:48:13.200 dealing with some kind of map or a hash map, right? 00:48:13.200 --> 00:48:17.280 Like, you know, what kind of concrete data structure you instantiate in Python is just like, yeah, 00:48:17.280 --> 00:48:17.760 it's a dictionary. 00:48:17.760 --> 00:48:18.640 It does its job. 00:48:18.640 --> 00:48:19.860 I don't really care how it works. 00:48:19.860 --> 00:48:20.780 And that's good. 00:48:20.780 --> 00:48:25.980 But it also means you're kind of, you're disconnected from a lot of the specific implementation details 00:48:25.980 --> 00:48:26.660 as a developer. 00:48:26.660 --> 00:48:27.560 Yeah, that's for sure. 00:48:27.560 --> 00:48:33.540 And until recently, dictionaries and still under some circumstances, they're unordered, 00:48:33.540 --> 00:48:35.940 which can cause all sorts of issues. 00:48:35.940 --> 00:48:40.680 If you read a file in, make some changes, save it back out in Python, you know, and you had 00:48:40.680 --> 00:48:45.020 that file in source control, it could look like 95% change where you just change like something 00:48:45.020 --> 00:48:46.880 from true to false or something silly like that. 00:48:46.880 --> 00:48:47.100 Right. 00:48:47.780 --> 00:48:52.080 And so there's actually, depending on the situations that you're in, there's all these 00:48:52.080 --> 00:48:53.920 other types of dictionaries that are pretty awesome. 00:48:54.160 --> 00:48:55.540 So we have ordered dict. 00:48:55.540 --> 00:49:01.260 I've seen the people that do data science and like really chain together generator expressions 00:49:01.260 --> 00:49:04.120 and list comprehensions and make massive use of default dict. 00:49:04.120 --> 00:49:08.440 There's chain map, which I don't think I had heard of chain map before. 00:49:08.440 --> 00:49:09.980 Maybe I heard of it and forgot about it. 00:49:09.980 --> 00:49:13.440 There's even mapping proxy type. 00:49:13.660 --> 00:49:17.200 So maybe take us through like when you might want to use those other things, like when dict 00:49:17.200 --> 00:49:18.600 or curly curly is not enough. 00:49:18.600 --> 00:49:24.100 I was also really, really amazed or, you know, really enjoyed learning more about chain map. 00:49:24.100 --> 00:49:25.380 So chain map is really cool. 00:49:25.380 --> 00:49:31.360 Basically, you can chain together multiple dictionaries and treat them like a single dictionary, like 00:49:31.360 --> 00:49:32.140 a single mapping. 00:49:32.460 --> 00:49:35.420 So you can group several dictionaries into one. 00:49:35.420 --> 00:49:39.320 And then when you do a lookup, actually the chain map is going to go and it's going to 00:49:39.320 --> 00:49:43.640 search all of these underlying dictionaries one by one until it finds a match. 00:49:43.640 --> 00:49:44.860 Yeah, that's really cool. 00:49:44.860 --> 00:49:50.020 To me, it felt like what I had previously done, if I wanted this behaviors, I would create a 00:49:50.020 --> 00:49:53.220 new dictionary and I would merge all of them into it. 00:49:53.220 --> 00:49:54.560 Then I would ask that question. 00:49:54.560 --> 00:49:59.620 But this lets you basically create the same behavior without actually building that other 00:49:59.620 --> 00:50:00.020 dictionary. 00:50:00.420 --> 00:50:04.660 And potentially you could create the chain map and then one of the underlying dictionaries 00:50:04.660 --> 00:50:05.200 could change. 00:50:05.200 --> 00:50:08.840 And then the answer coming back from the chain map would adapt to that, which is pretty awesome, 00:50:08.840 --> 00:50:09.080 right? 00:50:09.080 --> 00:50:09.600 That's right. 00:50:09.600 --> 00:50:15.040 And you don't incur that memory overhead because, you know, it's just like an abstract way to 00:50:15.040 --> 00:50:16.600 merge all these dictionaries together. 00:50:16.600 --> 00:50:19.400 And it's just the magic is in this search algorithm. 00:50:19.400 --> 00:50:24.480 But on the other hand, of course, you know, it can potentially be slower because the search 00:50:24.480 --> 00:50:25.360 actually needs to happen. 00:50:25.360 --> 00:50:28.900 So depending on, you know, if you change together thousands of dictionaries, maybe that's not 00:50:28.900 --> 00:50:29.320 a good idea. 00:50:29.320 --> 00:50:33.560 But if you, if you only have a couple of them and maybe you're combining a bunch of 00:50:33.560 --> 00:50:37.680 configuration dictionaries, then this could be really handy and you can just make sure, 00:50:37.680 --> 00:50:42.120 you know, okay, we have like a default setting dictionary with default settings, and then we 00:50:42.120 --> 00:50:45.680 can override them with more specific user settings. 00:50:45.680 --> 00:50:46.060 Right. 00:50:46.060 --> 00:50:48.900 Put the user settings and stuff at the beginning of the chain map. 00:50:49.260 --> 00:50:49.580 Yeah. 00:50:49.580 --> 00:50:51.240 That's nice. 00:50:51.240 --> 00:50:51.440 Yeah. 00:50:51.440 --> 00:50:54.560 The place I see this happening all the time on the web is because you've got to go, you've 00:50:54.560 --> 00:50:57.320 got a dictionary for like the route URL data. 00:50:57.500 --> 00:51:01.940 You've got one for the post, you've got one for the query string, you've got one for or else, 00:51:01.940 --> 00:51:04.580 somewhere else, headers, all sorts of stuff. 00:51:04.580 --> 00:51:08.060 And you can like combine them together into one place and ask like, did they give me this 00:51:08.060 --> 00:51:09.000 data somehow? 00:51:09.000 --> 00:51:10.660 I don't really care where it came from. 00:51:10.660 --> 00:51:12.720 Did they tell me their username or something? 00:51:12.720 --> 00:51:12.980 Right. 00:51:13.080 --> 00:51:13.160 Yeah. 00:51:13.160 --> 00:51:14.100 Where's the API key? 00:51:14.100 --> 00:51:14.600 Yeah, exactly. 00:51:14.600 --> 00:51:16.840 And then where's that print statement I'm looking for? 00:51:16.840 --> 00:51:18.520 All right. 00:51:18.520 --> 00:51:23.020 So another major class of data structures that I've found to be pretty interesting that you 00:51:23.020 --> 00:51:24.240 covered were arrays. 00:51:24.240 --> 00:51:29.020 So, you know, sort of the most common one of this is the list, but there's more than that, 00:51:29.020 --> 00:51:29.220 right? 00:51:29.220 --> 00:51:29.680 Oh, yeah. 00:51:29.680 --> 00:51:30.200 Yeah. 00:51:30.200 --> 00:51:34.560 And it's really similar to, you know, what we just discussed with the dictionaries where, 00:51:34.560 --> 00:51:38.760 well, if you're looking for an array, it's typically people will just tell you, 00:51:38.760 --> 00:51:39.860 well, use a Python list. 00:51:39.860 --> 00:51:40.940 It does everything you want. 00:51:41.100 --> 00:51:44.500 And, you know, behind the scenes, Python lists are actually dynamic arrays. 00:51:44.500 --> 00:51:48.600 So mutable dynamic arrays, they will grow and shrink with the data you put in. 00:51:48.600 --> 00:51:51.140 But there's actually other options as well. 00:51:51.140 --> 00:51:57.220 You know, you can, in a lot of ways, you can view a tuple as an immutable array, which means 00:51:57.220 --> 00:51:58.220 you can't change it. 00:51:58.220 --> 00:51:58.400 Right. 00:51:58.400 --> 00:51:59.420 You index into it. 00:51:59.420 --> 00:52:00.360 It has a length. 00:52:00.360 --> 00:52:03.820 You can say, give me the third, give me the fifth one, but it's totally static. 00:52:03.820 --> 00:52:06.100 Even the individual elements can't be changed, right? 00:52:06.100 --> 00:52:06.660 Exactly. 00:52:06.660 --> 00:52:06.920 Yeah. 00:52:06.920 --> 00:52:11.500 And I mean, the only problem you run into if you have like, you know, a nested data structure. 00:52:11.500 --> 00:52:17.280 So if you have a dictionary in your tuple, you can't put something else at that position in the 00:52:17.280 --> 00:52:20.720 tuple and replace the dictionary, but you could still reach in and modify the dictionary because 00:52:20.720 --> 00:52:22.560 the dictionary itself is not immutable. 00:52:22.560 --> 00:52:23.980 It's, you can modify it. 00:52:23.980 --> 00:52:26.080 And so sometimes, you know, that causes trouble for people. 00:52:26.080 --> 00:52:31.580 But in general, you know, yeah, you can absolutely treat a tuple like as an immutable array. 00:52:31.580 --> 00:52:33.060 Let's go back just for a second. 00:52:33.060 --> 00:52:37.340 Like one thing we kind of moved on from without talking much about it is mapping proxy type 00:52:37.340 --> 00:52:38.420 in the dictionary space. 00:52:38.420 --> 00:52:43.840 And so if you really wanted like this truly immutable tuple, you want to put a dictionary 00:52:43.840 --> 00:52:46.980 there, you could wrap it in this mapping proxy type, right? 00:52:46.980 --> 00:52:47.500 Oh yeah. 00:52:47.500 --> 00:52:48.380 That's a perfect segue. 00:52:48.380 --> 00:52:49.200 Yeah, exactly. 00:52:49.200 --> 00:52:57.020 So you, you could use this mapping proxy type class to make, take any standard dictionary and 00:52:57.020 --> 00:52:59.940 then to provide a read only view into that dictionary. 00:53:00.080 --> 00:53:05.240 So you can still access all of the variables, all the values, all the keys, but you cannot 00:53:05.240 --> 00:53:07.760 reach in and modify the dictionary. 00:53:07.760 --> 00:53:08.520 I mean, sure. 00:53:08.520 --> 00:53:14.140 You could just kind of pry that mapping proxy apart and then reach in and modify it. 00:53:14.140 --> 00:53:15.960 And this is probably not a good idea, but. 00:53:15.960 --> 00:53:19.680 That goes back to where the, like, you, you know, you shouldn't be doing it. 00:53:19.680 --> 00:53:23.780 And if you, if you mess it up, it's kind of your fault, not the APIs. 00:53:23.780 --> 00:53:27.540 It's like, yeah, you could install a kernel driver and patch the memory and. 00:53:27.540 --> 00:53:29.100 I rooted my machine and then it crashed. 00:53:29.100 --> 00:53:30.720 Oh, this thing is a crappy OS. 00:53:30.720 --> 00:53:32.200 Yeah. 00:53:32.200 --> 00:53:36.720 So that would, that, I mean, you could combine that for like a greater functional programming, 00:53:36.720 --> 00:53:39.640 immutable pass by value type of behavior, right? 00:53:39.640 --> 00:53:40.380 Yeah, you could do that. 00:53:40.380 --> 00:53:45.500 I mean, personally, I'm always thinking like, okay, at what point do we reach the level where 00:53:45.500 --> 00:53:51.720 we're really fighting against what the language wants us to do, but it is entirely possible, 00:53:51.720 --> 00:53:55.920 you know, to do what we just talked about, you know, you have a tuple and then instead 00:53:55.920 --> 00:53:59.400 of putting like dictionaries in there, I mean, you'd probably just go with a frozen dict class 00:53:59.400 --> 00:54:03.120 for that, but you could totally also wrap it in this mapping proxy type thing. 00:54:03.120 --> 00:54:07.780 And that way you really enforce that immutability as best as we can. 00:54:07.780 --> 00:54:09.940 And I think that's so nice about Python. 00:54:10.060 --> 00:54:12.940 The frozen dict is a little more obvious, but yeah, that is super nice. 00:54:12.940 --> 00:54:20.000 One of the things that traditional, let's say C, C++ arrays to a lesser degree, like 00:54:20.000 --> 00:54:27.300 some category of say C# arrays have is they have the same type in them and then they're 00:54:27.300 --> 00:54:28.160 tightly packed. 00:54:28.160 --> 00:54:30.800 And the tightly packed thing that I'm really thinking about, right? 00:54:30.900 --> 00:54:35.520 So if I say list and Python and I put number one, number two, number three in there, that's 00:54:35.520 --> 00:54:40.380 really a tightly packed set of pointers that points out to three things that are not anywhere 00:54:40.380 --> 00:54:40.980 near each other. 00:54:40.980 --> 00:54:41.700 Potentially. 00:54:41.700 --> 00:54:45.560 I mean, those are probably like pre-allocated and put next to you. 00:54:45.560 --> 00:54:49.920 Like I know one to 20255 or pre-allocated, but you know, in general, things in the arrays 00:54:49.920 --> 00:54:56.440 are not nearby each other, which means you're following a lot of pointers and there's a lot of GC type 00:54:56.440 --> 00:55:01.620 behavior, but there are structures that if you really want homogeneous types, tightly 00:55:01.620 --> 00:55:03.440 packed, you can get them, right? 00:55:03.440 --> 00:55:07.900 You can also get that in Python because like you said, with your standard list, there's really 00:55:07.900 --> 00:55:09.540 no guarantees. 00:55:09.540 --> 00:55:14.540 If your list of a couple of elements, it could actually be much larger than just those like 00:55:14.540 --> 00:55:18.880 five or six elements because it's pre-allocated to a bigger size and kind of shrinking and growing 00:55:18.880 --> 00:55:19.320 dynamically. 00:55:19.320 --> 00:55:24.640 And so if you want absolute control over how your data is laid out in memory, then you 00:55:24.640 --> 00:55:30.220 could use something like the array class from the array module that's in the Python standard 00:55:30.220 --> 00:55:30.600 library. 00:55:30.600 --> 00:55:38.540 And with this, you can actually say, Hey, I want an array off C style floats or ints, and 00:55:38.540 --> 00:55:44.480 you can just put in your values there and they will be laid out in memory exactly the way you 00:55:44.480 --> 00:55:45.000 request it. 00:55:45.000 --> 00:55:48.760 But it won't accept types that don't fit the declared data type, right? 00:55:48.760 --> 00:55:51.180 So if you say it takes floats, it won't take a string, right? 00:55:51.180 --> 00:55:53.300 It enforces that as well as the packing. 00:55:53.300 --> 00:55:53.840 Yeah, that's right. 00:55:53.840 --> 00:55:55.820 So you get some type safety there. 00:55:55.820 --> 00:55:59.960 So it's going to make sure that you're not putting in, I don't know, something crazy needs 00:55:59.960 --> 00:56:00.520 to be consistent. 00:56:00.520 --> 00:56:01.540 Let's skip ahead a little bit. 00:56:01.540 --> 00:56:03.560 We're actually, I thought we would get through more of these. 00:56:03.560 --> 00:56:05.100 I think we're going to run out of time pretty quick. 00:56:05.100 --> 00:56:09.000 But there's some stuff I really want to cover while we're here, because I think it's, it's 00:56:09.000 --> 00:56:09.660 quite interesting. 00:56:09.660 --> 00:56:12.660 You talk about stacks and you talk about queues. 00:56:13.420 --> 00:56:19.160 And I think this list that we were just talking about, it can be many things to many people. 00:56:19.160 --> 00:56:20.440 It can act as a queue. 00:56:20.440 --> 00:56:22.540 You can take the thing off the front. 00:56:22.540 --> 00:56:25.360 It has a pop to take things off the end. 00:56:25.360 --> 00:56:28.420 You can append that's like a synonym for push sort of. 00:56:28.420 --> 00:56:30.480 But there's also other queues. 00:56:30.480 --> 00:56:36.400 And there's also some really terrible performance issues if you try to use, say, like a list for 00:56:36.400 --> 00:56:36.860 a queue. 00:56:37.060 --> 00:56:39.920 So let's maybe touch on those things while we're on this topic. 00:56:39.920 --> 00:56:40.660 Yeah, for sure. 00:56:40.660 --> 00:56:45.060 So I mean, the list, again, it's such a versatile data structure in Python, right? 00:56:45.060 --> 00:56:51.220 And it's, I feel like they made exactly the right performance trade-offs when they implemented 00:56:51.220 --> 00:56:54.140 how list is actually implemented in the CPython interpreter. 00:56:54.140 --> 00:56:58.800 But on the other hand, it leads to those situations where you're like, oh yeah, you know, I can push 00:56:58.800 --> 00:56:59.700 and pop from a list. 00:56:59.700 --> 00:57:02.880 So I can totally make a stack or I can totally use it to make a queue. 00:57:03.440 --> 00:57:10.180 And I mean, you can, but the problem is, for example, if you use a list to make a queue, 00:57:10.180 --> 00:57:16.480 you can run into a situation where you'll just have terribly slow performance. 00:57:16.480 --> 00:57:22.280 Because if you enqueue an element in a list and you added, like you insert it at the front, 00:57:22.280 --> 00:57:26.160 this will actually shifting all of the other elements by one. 00:57:26.160 --> 00:57:30.740 So you're looking at a linear time operation just to insert one element. 00:57:30.740 --> 00:57:33.360 And that's really, really bad for a queue implementation. 00:57:33.360 --> 00:57:34.220 That's super bad. 00:57:34.220 --> 00:57:34.420 Yeah. 00:57:34.420 --> 00:57:37.260 If you're doing like the first in, first out behavior, right? 00:57:37.260 --> 00:57:39.020 So append, that's fine. 00:57:39.020 --> 00:57:39.720 It goes on the end. 00:57:39.720 --> 00:57:44.380 But every time you take an element off the front, it has to entirely copy every element. 00:57:44.380 --> 00:57:49.520 If there's a million items in your queue, that's a heavyweight DQ operation right there. 00:57:49.520 --> 00:57:53.060 So ironically, you should use this thing called DQ to fix it. 00:57:53.060 --> 00:57:54.060 Yeah. 00:57:54.060 --> 00:57:57.520 So there's this great, great little class in the collections module. 00:57:57.940 --> 00:58:00.420 And the collections module is just so awesome. 00:58:00.420 --> 00:58:04.040 If you're listening to this, for anyone who's listening to this show and they haven't heard 00:58:04.040 --> 00:58:07.000 or played with the collections module, check out the collections module. 00:58:07.000 --> 00:58:08.680 There's, it's just a treasure trove. 00:58:08.680 --> 00:58:12.740 And it's also fun reading, you know, just, just seeing what's available in there and the 00:58:12.740 --> 00:58:14.580 reasons for why it exists. 00:58:14.800 --> 00:58:20.320 And, but yeah, the collections module has this thing called a DQ or deck. 00:58:20.320 --> 00:58:21.760 I think some people pronounce it. 00:58:21.760 --> 00:58:25.540 And this is actually implemented as a linked list. 00:58:25.540 --> 00:58:32.940 So you can append and remove from both ends really, really fast because, you know, it's no, 00:58:32.940 --> 00:58:34.180 there's no shuffling around. 00:58:34.180 --> 00:58:37.100 It's just, okay, cut off the head or add something to the end. 00:58:37.100 --> 00:58:38.720 It's a single pointer operation. 00:58:38.720 --> 00:58:39.960 It's super, super fast. 00:58:39.960 --> 00:58:40.360 That's right. 00:58:40.680 --> 00:58:45.640 And the DE at the beginning is not the operation of removing the item from the Q, but that's 00:58:45.640 --> 00:58:48.540 the double ended Q, DEQ, right? 00:58:48.540 --> 00:58:49.280 Yeah, that's right. 00:58:49.280 --> 00:58:52.900 It's fast from, from the front and fast from the back as well. 00:58:52.900 --> 00:58:53.240 Right. 00:58:53.240 --> 00:58:59.620 And we have things like Q.Q and multiprocessing.Q and some other ones, special cases one. 00:58:59.920 --> 00:59:03.680 So I think it's really interesting to think about these because a lot of them, you know, 00:59:03.680 --> 00:59:06.400 like we said, you don't really discover them on your own. 00:59:06.400 --> 00:59:08.640 You have to kind of study them and seek them out. 00:59:08.640 --> 00:59:11.400 And you're like, oh, that's, I thought just Python was slow. 00:59:11.400 --> 00:59:13.720 List turns out to just be a really bad Q. 00:59:13.720 --> 00:59:17.000 So maybe I'll do something different, right? 00:59:17.000 --> 00:59:17.800 Yeah. 00:59:17.800 --> 00:59:20.640 So I think these are all really great, but I don't want to give people the impression that 00:59:20.640 --> 00:59:23.000 your book is all about just data structures, right? 00:59:23.000 --> 00:59:25.560 There's actually, you know, just one chapter. 00:59:25.560 --> 00:59:27.680 It just happens to be a super rich chapter. 00:59:27.680 --> 00:59:31.160 So maybe like we have some other stuff that was on deck that we're not probably going 00:59:31.160 --> 00:59:34.540 to be able to talk about in terms of time, but maybe just run us super quick through like 00:59:34.540 --> 00:59:35.820 what else you wanted to highlight. 00:59:35.820 --> 00:59:40.940 When I wrote this book, really the angle it's written from is that I don't want to create 00:59:40.940 --> 00:59:47.800 another technical reference, but I want to walk people through some actionable stuff and 00:59:47.800 --> 00:59:52.080 explain things step-by-step with examples that make sense. 00:59:52.080 --> 00:59:58.660 So I'm also covering kind of the classic features in Python that are often difficult to wrap your 00:59:58.660 --> 00:59:59.640 head around. 00:59:59.640 --> 01:00:05.340 And, you know, I don't know how much more time we have here, but for example, I think if 01:00:05.340 --> 01:00:11.240 people understand decorators and like really understand how they work internally, that is 01:00:11.240 --> 01:00:17.260 a huge leap from a beginner level understanding of Python, because you need to understand, you 01:00:17.260 --> 01:00:22.080 know, a couple of rather advanced features, like you need to understand, you know, what 01:00:22.080 --> 01:00:26.460 first class functions are that all functions can be treated are real full blown objects. 01:00:26.460 --> 01:00:30.220 And, you know, you can not just call them, but also look like a hand them around to other 01:00:30.220 --> 01:00:30.700 functions. 01:00:30.700 --> 01:00:31.060 Right. 01:00:31.060 --> 01:00:35.380 And closures, the concept of like variable capture and closures is front and center there. 01:00:35.680 --> 01:00:38.000 And that is all super important stuff. 01:00:38.000 --> 01:00:43.240 And just so by, you know, focusing on under really understanding how this feature works, 01:00:43.240 --> 01:00:50.660 you can actually learn a lot about Python and you can pick up a lot of other features and 01:00:50.660 --> 01:00:54.460 abilities that are going to help you in programming Python in general. 01:00:54.460 --> 01:00:59.920 And so a big part of the book is, you know, I really spent a lot of time on this and it's, 01:00:59.920 --> 01:01:01.560 it's been iterated over. 01:01:01.760 --> 01:01:06.220 I tested this with people and just walking them through understanding how decorators, 01:01:06.220 --> 01:01:10.860 for example, work, or, you know, walking them through iterators and then going from there 01:01:10.860 --> 01:01:15.680 to generators and then later generate expressions and really just explaining the logical connection 01:01:15.680 --> 01:01:19.240 between all of those and kind of structuring it away in a way where it's not just like, 01:01:19.240 --> 01:01:23.540 oh yeah, this is how it is, but kind of approaching the topic step by step. 01:01:23.540 --> 01:01:25.440 I think those are really, really nice things. 01:01:25.440 --> 01:01:30.960 You certainly building a simple decorator, like come up with some concept where it makes sense. 01:01:31.580 --> 01:01:35.720 And go through the motions of creating it will really, like you said, expose you to a lot. 01:01:35.720 --> 01:01:40.080 Some other things you talk about, you talk about the sushi operator, and I'm not going to give any 01:01:40.080 --> 01:01:40.520 more details. 01:01:40.520 --> 01:01:44.260 People have to check out your book to learn about that Python has a sushi operator. 01:01:44.260 --> 01:01:51.240 Design patterns like emulating a switch statement with dictionary dispatch, all sorts of stuff like 01:01:51.240 --> 01:01:51.400 that. 01:01:51.400 --> 01:01:53.840 So really just tons and tons of these little tricks. 01:01:53.840 --> 01:01:55.760 And you said the, it's like a buffet, right? 01:01:55.760 --> 01:01:57.120 So you don't have to take it in order. 01:01:57.120 --> 01:01:57.880 Yeah, that's right. 01:01:57.880 --> 01:02:02.380 So most of these chunks in this book or the sections in this book, you can actually, 01:02:02.380 --> 01:02:05.560 you know, jump around and just kind of look for things that interest you. 01:02:05.560 --> 01:02:10.200 They're usually pretty short and they all have a key takeaway section at the end. 01:02:10.200 --> 01:02:11.880 So you can quickly review this. 01:02:11.880 --> 01:02:16.300 And for example, I heard feedback on the data structures chapter where it's, you know, 01:02:16.300 --> 01:02:19.620 it's a great way to prepare yourself for a Python interview and just kind of, you know, 01:02:19.620 --> 01:02:24.500 get updated or get a refresher on how these standard data structures map to Python. 01:02:24.500 --> 01:02:29.700 I feel like people kind of, they take the easy way out and they ask these algorithm questions 01:02:29.700 --> 01:02:32.440 and these data structure questions in interviews. 01:02:32.440 --> 01:02:38.260 And yes, it's important, but I don't necessarily feel like if I don't know the most efficient 01:02:38.260 --> 01:02:42.380 particular queue for this type of operation, that doesn't necessarily mean I couldn't write 01:02:42.380 --> 01:02:47.260 an awesome web app that has, you know, a hundred thousand users a month and has no real performance 01:02:47.260 --> 01:02:48.200 pressure on it. 01:02:48.200 --> 01:02:48.460 Right. 01:02:48.460 --> 01:02:49.360 I agree with you. 01:02:49.360 --> 01:02:54.220 I mean, unfortunately, some people will really bust out the trick questions where it's like, 01:02:54.220 --> 01:02:56.280 ha ha, you didn't know about this like special case. 01:02:56.280 --> 01:02:58.580 That means you're a fool and we're never going to hire you. 01:02:58.580 --> 01:03:03.460 But the reason I don't like those is I feel like those tend to advantage the people that 01:03:03.460 --> 01:03:08.460 have CS degrees, but not necessarily better programming skills than people who are self-taught. 01:03:08.460 --> 01:03:11.740 So I really like that your book kind of backfields that information for people. 01:03:11.740 --> 01:03:12.100 Thanks. 01:03:12.100 --> 01:03:13.660 I mean, that was one of the goals, right? 01:03:13.720 --> 01:03:18.960 Where it's like, yeah, a lot of this stuff, you don't need to spend like four years in 01:03:18.960 --> 01:03:22.580 university just to understand what a hash table is. 01:03:22.580 --> 01:03:22.940 Right. 01:03:22.940 --> 01:03:25.640 And it's, I don't like it when people create that impression. 01:03:25.640 --> 01:03:32.380 And so, you know, I feel like if you have a good practical understanding or practical programming 01:03:32.380 --> 01:03:38.100 skill, then it will be in most cases, like pretty easy for someone to fill in those gaps in 01:03:38.100 --> 01:03:43.220 our knowledge and, you know, to satisfy the people who ask the more computer science motivated 01:03:43.220 --> 01:03:44.080 questions, I guess. 01:03:44.080 --> 01:03:44.720 Yeah, absolutely. 01:03:44.720 --> 01:03:45.260 All right. 01:03:45.260 --> 01:03:48.620 Well, let's leave it there for the book because we are definitely going to run out of time. 01:03:48.620 --> 01:03:51.920 So I do want to talk about a few other projects that you have going. 01:03:51.920 --> 01:03:54.780 First of all, you have this thing called Pythonista Cafe. 01:03:54.780 --> 01:03:58.280 Did you open like some kind of like coffee shop or something? 01:03:59.520 --> 01:04:03.600 That's my lifelong dream, you know, open a coffee shop, write books. 01:04:03.600 --> 01:04:05.500 Answer a Python question before you're permitted in. 01:04:05.500 --> 01:04:05.880 Yes. 01:04:05.880 --> 01:04:12.520 So Pythonista Cafe, it all started when occasionally I read Reddit or Hacker News and it can be great. 01:04:12.520 --> 01:04:18.880 And it can also be like people have some weird personas on these forums sometimes, you know, 01:04:18.880 --> 01:04:22.620 and people kind of lash out at each other and get really worked up. 01:04:23.020 --> 01:04:27.740 And I remember this one time, like somebody made a post on Reddit, one of the Python forums 01:04:27.740 --> 01:04:30.600 on Reddit and said, hey, I'm this 14 year old guy. 01:04:30.600 --> 01:04:31.720 I really love Python. 01:04:31.720 --> 01:04:35.580 I made these tutorial videos on my YouTube channel about, you know, building a Flask app. 01:04:35.580 --> 01:04:36.720 What do you think about this? 01:04:36.720 --> 01:04:41.120 And like the first person to reply is like, oh, you're teaching it all wrong and you should 01:04:41.120 --> 01:04:45.020 have never created these videos and you'll basically, you'll never be a good programmer 01:04:45.020 --> 01:04:45.620 and blah, blah, blah. 01:04:45.620 --> 01:04:46.540 Who do you think you are? 01:04:46.540 --> 01:04:50.340 He's probably like in the top, like 5% of all like 14 year old programmers. 01:04:50.340 --> 01:04:51.060 I mean, come on. 01:04:51.060 --> 01:04:52.380 And that is nuts, right? 01:04:52.380 --> 01:04:57.040 Like, how can you, how can you, I was just almost like sitting in front of a computer 01:04:57.040 --> 01:04:59.560 shaking and getting angry at this person. 01:04:59.560 --> 01:05:01.800 And it just seems so crazy. 01:05:01.800 --> 01:05:04.020 But the problem is, I mean, this is, this is real, right? 01:05:04.020 --> 01:05:04.720 Like this happens. 01:05:04.720 --> 01:05:06.580 I mean, most of the time it's a great forum. 01:05:06.580 --> 01:05:13.020 It's a great community, but some people, they are just crazy when it, the knee jerk reactions 01:05:13.020 --> 01:05:13.460 they get. 01:05:13.460 --> 01:05:15.020 And I really liked that. 01:05:15.020 --> 01:05:19.160 And so I reached out to a bunch of people and said, hey, so here's an idea. 01:05:19.160 --> 01:05:24.280 We're going to do a Python forum, an online forum where people can discuss Python, you 01:05:24.280 --> 01:05:26.700 know, you can bring their code and get feedback on their code. 01:05:26.700 --> 01:05:31.300 And we're going to talk about all things Python, but we're going to do it in private. 01:05:31.300 --> 01:05:34.900 So it won't be a public forum and there will be an application process to get in. 01:05:35.700 --> 01:05:39.220 And I launched that at the beginning of this year. 01:05:39.220 --> 01:05:44.600 So 2017, I don't know when the show is going to come out, but so far it's been a really, 01:05:44.600 --> 01:05:45.360 really cool experience. 01:05:45.360 --> 01:05:48.300 We have about 120 people in the forum right now. 01:05:48.300 --> 01:05:52.960 And it is, I don't like the word safe space, but in a way it is a safe space where you can 01:05:52.960 --> 01:05:57.280 just go and post some code and you're going to get like really, really positive and encouraging, 01:05:57.280 --> 01:05:58.600 helpful comments. 01:05:58.940 --> 01:06:02.760 And there's no danger of someone going in and be like, oh, you're the worst like 14 01:06:02.760 --> 01:06:04.180 year old programmer in the world. 01:06:04.180 --> 01:06:06.700 And you should go back to where you came from. 01:06:06.700 --> 01:06:08.760 That's Pythonista Cafe in a nutshell. 01:06:08.760 --> 01:06:09.600 Nice. 01:06:09.600 --> 01:06:10.100 That's awesome. 01:06:10.100 --> 01:06:11.420 So yeah, you've got that going. 01:06:11.420 --> 01:06:15.640 Did you do a book or videos or something for Sublime for Python developers? 01:06:15.640 --> 01:06:16.780 Yeah, I also did that. 01:06:16.780 --> 01:06:20.220 So I have a couple of courses that I offer on my website. 01:06:20.220 --> 01:06:22.380 And one of them is also on Talk Python training. 01:06:22.380 --> 01:06:28.320 And so one of them is a complete course on setting up Sublime Text for Python development. 01:06:28.320 --> 01:06:31.320 So like an end-to-end, step-by-step course. 01:06:31.320 --> 01:06:35.900 And that consists of a couple of modules and, you know, like workbooks and video lessons on 01:06:35.900 --> 01:06:40.780 how to get a really, really awesome and productive Python environment with the Sublime Text editor, 01:06:40.780 --> 01:06:42.240 because that's my favorite editor. 01:06:42.240 --> 01:06:45.360 I know you really enjoy PyCharm and I think that's a great option too. 01:06:45.360 --> 01:06:49.640 But for me, Sublime Text has just been, it's just been a great setup. 01:06:49.640 --> 01:06:51.900 And you can script it with Python, which is nice too. 01:06:51.900 --> 01:06:54.040 It's definitely a very Pythonic place to be. 01:06:54.040 --> 01:06:54.480 That's awesome. 01:06:54.480 --> 01:06:56.000 So yeah, that's cool. 01:06:56.000 --> 01:06:59.540 If people want to learn more about like getting the most out of Sublime, they can check that out. 01:06:59.540 --> 01:07:04.740 You've got like the pip dependencies course available both on your website and Talk Python training, 01:07:04.740 --> 01:07:06.660 which I thought that was really awesome. 01:07:06.660 --> 01:07:08.200 I mean, people are like, well, I know pip. 01:07:08.200 --> 01:07:13.680 Like now this is like really, really the right way to sort of manage dependencies in your app 01:07:13.680 --> 01:07:15.800 or other packages that you're using. 01:07:15.800 --> 01:07:16.580 It's really great. 01:07:16.580 --> 01:07:19.060 So I definitely enjoyed checking that out as well. 01:07:19.060 --> 01:07:19.640 All right. 01:07:19.640 --> 01:07:21.980 So I think you've given us a spoiler for this. 01:07:21.980 --> 01:07:24.240 The last two questions here, at least the first one and the last two. 01:07:24.240 --> 01:07:25.200 Favorite editor? 01:07:25.200 --> 01:07:26.580 No, it's Sublime. 01:07:26.580 --> 01:07:26.900 Bye, John. 01:07:26.900 --> 01:07:28.440 Yeah, that's awesome. 01:07:28.440 --> 01:07:30.220 Yeah, I think I like Sublime as well. 01:07:30.220 --> 01:07:31.600 I definitely use it some of the time. 01:07:31.600 --> 01:07:32.160 Very cool. 01:07:32.160 --> 01:07:35.020 And notable PyPI package this time around? 01:07:35.020 --> 01:07:35.360 Yeah. 01:07:35.360 --> 01:07:40.060 So this time around, it'll be Django because Django 2.0 just came out. 01:07:40.060 --> 01:07:40.980 That's big news. 01:07:40.980 --> 01:07:42.900 What's the biggest piece of news about Django 2.0? 01:07:42.960 --> 01:07:46.020 I think the new URL routing syntax is pretty cool. 01:07:46.020 --> 01:07:47.160 It looks really nice. 01:07:47.160 --> 01:07:52.600 And for me, Django, you know, it just represents so well what Python stands for. 01:07:52.600 --> 01:07:56.180 It's really, you know, this is a piece of software that you can depend on. 01:07:56.180 --> 01:07:57.000 It's mature. 01:07:57.160 --> 01:08:01.540 And it's for when you actually want to get work done and not be worried about having 01:08:01.540 --> 01:08:04.820 to rewrite your whole stack in six or eight months down the road. 01:08:04.820 --> 01:08:07.840 And I feel like, you know, the Django team is so awesome. 01:08:07.840 --> 01:08:11.300 And it's a huge achievement about what they've done over the last couple of years. 01:08:11.300 --> 01:08:13.900 And yeah, so, you know, my pick is Django. 01:08:13.900 --> 01:08:14.520 Awesome. 01:08:14.520 --> 01:08:15.720 New 2.0. 01:08:15.720 --> 01:08:16.840 Yeah, the shiny Django. 01:08:16.840 --> 01:08:21.300 And the other major news around there is that they've dropped legacy Python support. 01:08:21.300 --> 01:08:23.140 No more Python 2 in Django 2. 01:08:23.140 --> 01:08:23.580 Oh, yeah. 01:08:23.580 --> 01:08:25.460 Yeah, ironically, given the numbers there. 01:08:25.460 --> 01:08:29.520 I think that's a super positive move. 01:08:29.520 --> 01:08:35.040 Just the fact that Django switched their default behavior in their documentation from Python 01:08:35.040 --> 01:08:39.460 2 to Python 3 made a huge dent in the consumption of Python 3 on PyPI. 01:08:39.460 --> 01:08:42.440 And now I imagine this is just going to take it up a notch. 01:08:42.440 --> 01:08:43.700 That's great. 01:08:43.700 --> 01:08:44.340 Yeah, totally. 01:08:44.340 --> 01:08:45.340 I mean, I saw that. 01:08:45.340 --> 01:08:49.780 Like, I've been, you know, I have a couple of videos on YouTube on should I be using Python 01:08:49.780 --> 01:08:50.560 2 or Python 3? 01:08:50.560 --> 01:08:55.240 And just a couple of months ago, you know, people were like, oh, yeah, this is a valid question. 01:08:55.240 --> 01:08:59.100 And now it's like every time I tweet this video, someone is like, there's no question 01:08:59.100 --> 01:08:59.460 about it. 01:08:59.460 --> 01:09:02.100 Like Python 3, like, don't go with Python 2. 01:09:02.100 --> 01:09:03.600 So that's great news, I think. 01:09:03.600 --> 01:09:04.360 I totally agree. 01:09:04.360 --> 01:09:08.020 I feel like the last six months or so it really has become like, why would you even ask this 01:09:08.020 --> 01:09:08.340 question? 01:09:08.340 --> 01:09:10.240 Like, this is sort of a deprecated video. 01:09:10.240 --> 01:09:11.180 You should just take it down. 01:09:11.180 --> 01:09:14.020 But that's really positive for the whole community. 01:09:14.020 --> 01:09:14.480 Awesome. 01:09:14.480 --> 01:09:15.380 All right. 01:09:15.380 --> 01:09:16.820 So final call to action. 01:09:16.820 --> 01:09:17.720 People can get your book. 01:09:17.720 --> 01:09:19.620 They can check out Python East Cafe. 01:09:19.620 --> 01:09:21.680 There's all sorts of stuff they can do to learn more about this, right? 01:09:21.680 --> 01:09:25.580 If you're listening to the show and you found interesting what Michael and I talked about, 01:09:25.580 --> 01:09:29.840 and you want to learn more and kind of go from beginner to intermediate Python skills and 01:09:29.840 --> 01:09:36.860 beyond without complex jargon and other crazy stuff, then you should download the free sample 01:09:36.860 --> 01:09:37.680 chapter for my book. 01:09:37.680 --> 01:09:42.620 You can just go to pythontricksbook.com or also just go to Amazon and search for Python 01:09:42.620 --> 01:09:42.920 tricks. 01:09:43.620 --> 01:09:48.600 And the book also comes with a free bonus toolkit where people can get more than two 01:09:48.600 --> 01:09:53.200 hours worth of video material to help reinforce some of the main lessons in the book. 01:09:53.200 --> 01:09:56.280 So yeah, go check it out at pythontricksbook.com. 01:09:56.280 --> 01:09:56.600 Awesome. 01:09:56.600 --> 01:09:57.920 All right, Dan, thanks for being here. 01:09:57.920 --> 01:09:59.380 It's fun, as always, to chat with you. 01:09:59.380 --> 01:10:00.780 Hey, thanks for having me on the show again. 01:10:00.780 --> 01:10:01.220 It was great. 01:10:01.220 --> 01:10:01.580 You bet. 01:10:01.580 --> 01:10:01.920 Bye. 01:10:03.520 --> 01:10:06.100 This has been another episode of Talk Python To Me. 01:10:06.100 --> 01:10:10.600 Today's guest has been Dan Bader, and this episode has been brought to you by Linode and 01:10:10.600 --> 01:10:11.060 Rollbar. 01:10:11.060 --> 01:10:15.080 Linode is bulletproof hosting for whatever you're building with Python. 01:10:15.080 --> 01:10:19.440 Get your four months free at talkpython.fm/linode. 01:10:19.440 --> 01:10:21.960 Just use the code Python17. 01:10:21.960 --> 01:10:24.980 Rollbar takes the pain out of errors. 01:10:24.980 --> 01:10:30.060 They give you the context and insight you need to quickly locate and fix errors that might have 01:10:30.060 --> 01:10:32.680 gone unnoticed until your users complain, of course. 01:10:32.680 --> 01:10:37.500 As Talk Python To Me listeners, track a ridiculous number of errors for free at 01:10:37.500 --> 01:10:39.780 rollbar.com slash talkpythontome. 01:10:39.780 --> 01:10:42.260 Are you or a colleague trying to learn Python? 01:10:42.260 --> 01:10:46.920 Have you tried books and videos that just left you bored by covering topics point by point? 01:10:46.920 --> 01:10:50.960 Well, check out my online course, Python Jumpstart by Building 10 Apps at 01:10:50.960 --> 01:10:55.520 talkpython.fm/course to experience a more engaging way to learn Python. 01:10:55.520 --> 01:10:58.540 And if you're looking for something a little more advanced, 01:10:58.700 --> 01:11:02.880 try my Write Pythonic Code course at talkpython.fm/pythonic. 01:11:02.880 --> 01:11:05.600 Be sure to subscribe to the show. 01:11:05.600 --> 01:11:07.820 Open your favorite podcatcher and search for Python. 01:11:07.820 --> 01:11:09.060 We should be right at the top. 01:11:09.060 --> 01:11:12.380 You can also find the iTunes feed at /itunes, 01:11:12.380 --> 01:11:14.440 Google Play feed at /play, 01:11:14.440 --> 01:11:18.340 and direct RSS feed at /rss on talkpython.fm. 01:11:18.340 --> 01:11:20.240 This is your host, Michael Kennedy. 01:11:20.240 --> 01:11:21.600 Thanks so much for listening. 01:11:21.600 --> 01:11:22.660 I really appreciate it. 01:11:22.660 --> 01:11:24.600 Now get out there and write some Python code. 01:11:24.600 --> 01:11:24.680 See you soon. 01:11:24.680 --> 01:11:45.300 I'll see you next time.