#244: Top 10 Real Python Articles of 2019 Transcript
00:00 Michael Kennedy: We've come to the end of 2019. Python 2 has just a handful of days before it goes unsupported. And I've met up with Dan Bader from RealPython.com to look back at the year of Python articles on his website. We dive into the details behind 10 of his most important articles from the past year. This is Talk Python To Me, Episode 244, recorded November 8, 2019. Welcome to Talk Python To Me, a weekly podcast on Python, the language, the libraries, the ecosystem and the personalities. This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy. Keep up with the show and listen to past episodes at talkpython.fm and follow the show on Twitter via @talkpython. This episode is sponsored by Linode and brilliant.org. Please check out what they're offering during their segments. It really helps support the show. Hey there, I want to take just a moment before we get to the interview and say thank you. It's the end of 2019, looking back, it's been a great year for the podcast and all the other stuff we're doing, like our courses. And it's been really humbling to get messages from all of you about how the podcast is helping you in some way or the benefits you're getting from it. And I just want to say thank you for listening because it's a true honor to be able to create this podcast for you. It's a lot of work, but it's entirely worth it. It's really, really great and it couldn't be done without you listening and sharing it. So thank you, thank you, thank you. Hope your 2019 was great as well. Now let's chat with Dan. Dan, welcome back to Talk Python To Me.
01:43 Dan Bader: Hey, it's great to be back, man.
01:44 Michael Kennedy: It's great to have you back. It's been awhile since you've been on Talk Python, but not too long ago since you were on Python Bytes, that was fun.
01:50 Dan Bader: Yeah, that's right. We practically just finished recording that and yeah, it's great with Cecil Phillip and yeah, I had some good links that week, I think.
01:58 Michael Kennedy: Yeah, absolutely. So I'm pretty excited about 2019. It was a good year, how was it for you?
02:03 Dan Bader: It was a very, very busy year, I would say. Yeah.
02:08 Michael Kennedy: Yeah, I feel like for you guys, Real Pythoners come along a long ways, you've got a lot of authors, you've got this process going, you've got your editorial, your editing and you're overseeing how the content creation is going and you're making a big difference, I think.
02:22 Dan Bader: Thanks, that's good to hear. Yeah, it's just been this incredible year. We're at 75 authors and video instructors published on the site now. So I want to get to 100 next year. That would be a nice just cool achievement, I think. And we also just recently hit 2 million visitors, unique visitors or readers in a single month, which is this incredible. Let me, it totally sounds like I'm super bragging here, but it's I literally can't wrap my brain around that. It's just nuts and really cool just to see that growth and how it's resonating and how we're getting really, really positive feedback, yeah.
03:00 Michael Kennedy: Yeah, I think that's really positive and congratulations.
03:03 Dan Bader: Thank you.
03:04 Michael Kennedy: And I think it speaks, one, to all the work that you're doing that you talked about. It also speaks to just Python's growth in general, right? You're riding two curves and they're both going in the right direction.
03:15 Dan Bader: Yeah, that's true. So how was your 2019?
03:17 Michael Kennedy: My 2019 was amazing. Didn't skip a single episode on any of the podcasts and I think that's a pretty big accomplishment actually.
03:25 Dan Bader: That's huge, yeah.
03:26 Michael Kennedy: And released a bunch of classes. I feel like we've covered some important stories on the podcast. That's one of the things I try to do. We can cover every web framework and the person who creates it and that's great and so on, but I really want to highlight that Python is not just for web developers or straight down the middle of the road data scientists. We've had medieval Islamic philosophers and we've had people doing machine learning or a particle collisions and all sorts of stuff. That might've been back in 2018, but those kinds of stories are really interesting. I think we had a decent amount of those and I'm really happy to be able to share those edge stories that I think are so interesting.
04:07 Dan Bader: Yeah, I think that's super cool and I think a podcast is just such a great format for it as well where somebody can come on the show and join you there and really give the listener a chance to understand why this is cool and what the motivation. That's always the most interesting thing for me when I listen to your show, figuring out why is your guest doing that, why are they so into researching Islamic philosophy with Python, which are two topics I would have never imagined you would combine in some way. And then I listen to the show and I'm like, oh man, it's so cool how broad this is what people are doing with Python.
04:40 Michael Kennedy: Yeah, you listen to the story and it makes perfect sense. You're like, of course, you should be doing that. And the thing I like about those types of stories is there's a lot of people that think, oh, I'm not a programmer or it doesn't make sense for me to do that or whatever, I'm just a stock trader, I'm just a biologist and then you hear that and you're like alright, if somebody can use it for philosophy, 1000-year-old scrolls, I should be able to find a way to make use of this in my much more mainstream type of job. Obviously, there's all these amazing things people can do, they just got to be a little creative to do it.
05:11 Dan Bader: Yeah, absolutely. I feel like we talked about this before about this whole idea of the dark matter developer or someone who doesn't actually really identify as a developer or a programmer, but there's so many people out there who are practically programmers or they're working with code, they're writing code, but they don't really see it that way.
05:29 Michael Kennedy: A big enough part of the community to actually come along and come to the conferences or blog about programming, they're probably blogging about something else that they care about. Something like that, right? Sweet, cool, well let's talk about what we're going to focus on for this show. So the idea is we're going to take 10 of your popular bookicles, book-articles, your articles that are near book style on Real Python and just pick 10 of them. We're going to call it the top 10, but it's not necessarily top 10 by viewer traffic. It's the ones you wanted to highlight from the year, right?
06:03 Dan Bader: Yeah, so I really wanted to give a chance to sample a wider variety of topics because if you go purely by traffic numbers, things are going to get overshadowed by popular terms that people search for.
06:16 Michael Kennedy: Look, it's four Django articles or whatever, right, just 'cause people are searching for that or whatever.
06:20 Dan Bader: Yeah, so we assembled a list of 10 articles that we wanted to highlight and then go over and share with you.
06:28 Michael Kennedy: Alright, where are we starting?
06:29 Dan Bader: Sweet, so we're starting with an article that's called How To Run Your Python Scripts by Leodanis Pozo Ramos and it sounds simple.
06:40 Michael Kennedy: Right, python script.py.
06:45 Dan Bader: Yep, that's what we do most of the time. Hit Ctrl-R or something like that, F5. And this article is cool because it, of course, talks about that, but then it goes really, really deep into the behind the scenes in what some of the other ways are that you can possibly use to run Python code. So you could just load the string from off a script and then just eval it or there's the importlib pmodule in Python 3 that you could use and there's all kinds of other more complex methods where you get deeper and deeper into CPython.
07:23 Michael Kennedy: You could do python -c and some code right?
07:27 Dan Bader: You could also do that if you wanted to run a code snippet from the command line. And I just love this article because it starts with the really simple and straightforward and main use case and then it goes deeper and deeper and deeper into all the different alternatives and what the differences between running a module with a python -m versus actually just running it by python, space and then the file of the file name and running it from the command line. And yeah, for that reason, I wanted to highlight that article.
07:57 Michael Kennedy: Okay, yeah, that's really cool. And one of the things I like about a couple of the articles that we're covering are I look at the title and I go, yeah, I know that and then I look at the article and it's like I don't know how many words, but readability suggests this might be over an hour to read this article. I'm like, wait, I thought that was simple and I knew it. And that makes me think, oh, I actually might learn something here if I just pay attention. This is going deeper or into a different area than... 'Cause if I thought it was this simple and it's this, then clearly I'm missing something.
08:28 Dan Bader: Yeah, as the person running the site and working on the platform there, I love seeing surprises like that because it's always a team of us that's working on the articles. We have multiple review stages and we review the outline and then we review the script and there's a technical review. And just seeing these things grow and become a real Python article is... I just really enjoy that process and being a part of it. So yeah, this is a great example, I think, of that.
08:56 Michael Kennedy: Yeah, quite cool. So covers a bunch of stuff and probably something... There's definitely a few suggestions in there that I didn't know. Alright, what's number two?
09:05 Dan Bader: Number two is called 13 Project Ideas for Intermediate Python Developers by Habeeb Shopeju. And this was born out of a lot of questions that we received over email or Twitter and also most recently now our Real Python community Slack where people are asking, I feel like I know how to use Python, but I don't know what I should build with it, what should I do with it?
09:29 Michael Kennedy: I've learned the language, I know Loops, I know how to do strings like create a dictionary, get stuff in and out of it, but what can I actually build that is the next step? 'Cause that's often very challenging. It's not just challenging on maybe a lack of creativity. It's challenging in a like, oh, you know what would be cool to build, Instagram. Like, no, it wouldn't be cool to build. It's millions of lines of code. You know what would be cool to build is a timer. Like, no, it's boring and it's too short. Like what is the right size where it's challenging but I can reasonably expect to do it if I put in some effort, right?
10:00 Dan Bader: And that's a really hard one. Back in the day when I learned how to code or first started, I guess you never really stop learning how to program, I was in these game development forums and there was every single week, there was a new person joining, they were like I want to build this MMORPG or I want to build this massive thing. And so everybody was working on these massive projects that never really went anywhere and I think that could be really, really frustrating. And so my answer to that question, what should I build as an intermediate developer was usually just pick whatever, just take a command line app that you use and try to emulate, try to write your own version of it. But the problem is that doesn't really work for some learners, for some students and so we wanted to give them a list with ideas. Here's some things that we think you could probably pull off, you have a fighting chance of actually building this app and it's not going to be a World of Warcraft, but it's going to be a cool alarm tool or a little file manager or a little note-taking application.
10:55 Michael Kennedy: Yeah, give us a sense of some of the ideas you got there.
10:58 Dan Bader: Yes, so the ones that I just mentioned.
11:01 Michael Kennedy: Yeah, exactly, so MP3 player, URL shortener, file rename.
11:07 Dan Bader: Yeah, or the contact book, I think, is also something interesting where there's different ways you could store the data. It could just be a little address book or it could be as simple as just storing a dictionary to a text file or then you could get progressively more interesting there and have a little database maybe.
11:27 Michael Kennedy: Could be SQLite and then you could start using SQLAlchemy 'cause you don't want to be writing inline SQL and then become little Bobby Tables.
11:35 Dan Bader: Yeah, that's right. If someone could take your great free MongoBD course and they'd use that, all kinds of options there...
11:42 Michael Kennedy: Yeah, they could certainly level these up. They could put them online, all kinds of cool stuff. Yeah, so I like it. You got it broken down to web, GUI and command line. That's a pretty good breakdown.
11:51 Dan Bader: Yeah, that's right, we tried to give a high level overview and then depending on what you're interested in, you could pick the right project for you.
11:57 Michael Kennedy: Yeah, super. Alright, what's next?
11:59 Dan Bader: Alright, so I think we are at article number three and what I wanted to highlight there is the article is called Three Ways of Storing and Accessing Lots of Images in Python by Rebecca Stone. And I think this article is cool because again it's something that I never really thought about before. I was like, okay, my Django app uses a bunch of static images, there's just a folder in there.
12:22 Michael Kennedy: Right, /static, /img or something, right?
12:25 Dan Bader: Yep, but what if that maybe doesn't work so great anymore? Think you're storing a massive amount of images. You have some, I don't know, some robot, some probe that's going to Mars and you have lots, you have terabytes of images and where are you going to store them or how are you going to make this manageable?
12:42 Michael Kennedy: Right, are you would create some kind of automated IoT doorbell that always snapshots whatever's close, right?
12:50 Dan Bader: Yeah and if your house gets broken in a lot, eventually, you have too many images and you got to figure out what to do with them.
12:55 Michael Kennedy: That's right, why are all these people at my house? You're killing my storage. Alright, so what are some of the suggestions?
13:00 Dan Bader: Yeah, so the article goes into three techniques stores. So the first one is just store them on disks as .png files or jpg or what have you and then the second option is using a memory mapped database called LMDB and the third option is using a hierarchical data format like HDF5 and the latter two, I'd never really heard about before but it turns out of course that there is a lot of Python tooling available for these things and so they provide a number of interesting features. So for example, there's compression that you could use to potentially limit your disk usage and there's just lots of good tooling if that's a problem that you're facing that people can use with Python.
13:50 Michael Kennedy: Yeah, this is interesting. I had never heard of LMDB, but apparently it's lightning memory map databases, which sounds...
13:56 Dan Bader: It sounds fast.
13:58 Michael Kennedy: Yeah, it's like, I should definitely check that out, find a use case for that 'cause that sounds cool.
14:02 Dan Bader: Yeah, you got to build that magical doorbell robot.
14:05 Michael Kennedy: Right, maybe selfies for robots or something, they could just do it all day long. Alright, awesome. Alright, so what's number four?
14:12 Dan Bader: Number four is called Speed Up Your Python Program with Concurrency by Jim Anderson.
14:17 Michael Kennedy: Oh, this is one that definitely, definitely resonates with me.
14:20 Dan Bader: It's yeah, you have a lot of great material on asyncio and working with parallelism and concurrency with Python. The idea for this article was to give the reader an overview of what different types of concurrency that are out there and what does it mean if a program is CPU bound versus IO bound and which options make sense using. It wants you to use threading versus multiprocessing or asyncio and we also added an interactive quiz to it, so that if you're reading this, you can really make sure, okay, I actually understood these concepts because they're pretty difficult to take in the first time.
14:59 Michael Kennedy: Yeah, that's the kind of thing that just needs to wash over you several times until you're like, alright, I'm starting to get the feel of this thing.
15:05 Dan Bader: Right, get burned by it a couple of times and then you're like, oh no, I got to rearchitect this again.
15:09 Michael Kennedy: Exactly and I think this is important in Python because I think Python's concurrency story is both amazing, but non-obvious in some ways. And what I mean by that is a lot of programming languages, you can leverage computational concurrency by using just threads, right, because I got this thing believes it has 12 threads, my MacBook here. It has six hyperthreaded cores. So if I were to write a single threaded program, it'll get 8 or 9% CP usage and that's it. If I want to make that go faster in a lot of languages, C++, C#, whatever, I can just create a bunch of threads and it can start running on all of those different threads, but in Python we have the GIL, so it doesn't work. And that's, I think, actually caused a lot of challenges because people say, "Well, that means Python's currency is broken." Not broken, it just needs a clearer mental model of when to apply each technique.
15:59 Dan Bader: Yeah, it's got a manual gear shift. It's not broken, but that car is also not going to go.
16:05 Michael Kennedy: It drives in the day but it won't drive at night. Put it in night mode. It won't go.
16:10 Dan Bader: Put it in N.
16:11 Michael Kennedy: Yeah, exactly, for example if it's I/O bound, probably what you want to do is something to do with asyncio, but if it's computational, you really need to do at least for the moment something with multiprocessing. And so it compares those types of things, huh?
16:26 Dan Bader: Yeah, exactly and like I said, we have this quiz at the end that you can take and then really make sure, okay, I understand what the differences are between these concurrency models.
16:37 Michael Kennedy: This portion of Talk Python To Me is brought to you by Linode, whether you're working on a personal project or managing your enterprise's infrastructure, Linode has the pricing, support and scale that you need to take your project to the next level. With 11 data centers worldwide, including their newest data center in Sydney, Australia, enterprise grade hardware, S3 compatible storage and the next generation network, Linode delivers the performance that you expect at a price that you don't. Get started on Linode today with a $20 credit and you get access to native SSD storage, a 40 gigabit network, industry leading processors, their revamped pod manager, cloud.linode.com, root access to your server along with their newest API and a Python CLI. Just visit talkpython.fm/linode when creating a new Linode account and you'll automatically get $20 credit for your next project. Oh, and one last thing, they're hiring. Go to linode.com/careers to find out more. Let them know that we sent you. And number five.
17:37 Dan Bader: Alright, number five. Build a Recommendation Engine with Collaborative Filtering by Abhinav Ajitsaria. And this is, what do you think this is?
17:47 Michael Kennedy: I'm reading the Real Python article and it says you might also like these other three or something like that.
17:52 Dan Bader: Exactly, yep.
17:53 Michael Kennedy: Or an offline course, you might also like this one, right, it's a good follow on for various reasons. People who took this course usually took that one next or people who have read this article also shared that other article or something.
18:05 Dan Bader: Yeah, exactly, it's about building recommendation engines like you would have on pretty much any larger website like Netflix or Amazon. They're all recommending you products or movies that you might enjoy based on what you already watched. And a lot of times what they do is they look at, build a profile of the things that you watched and then finding similar users, other users on the platform that watched those movies and enjoyed them and then based on that trying to figure out, okay, what did these other people also watch and enjoy and maybe we can recommend that back to you and then hopefully you'll have a good time on the platform.
18:41 Michael Kennedy: Yeah, that sounds really cool. It sounds very relevant to data scientists and there's probably a lot of data science algorithms in there.
18:47 Dan Bader: Yeah, absolutely, I think there's some cool stuff happening there and there's some matrix math. And what I like about this article that I really like how it turned out from a typesetting perspective. So that was a really big aspect of building the new Real Python CMS and hosting platform built on Python 3, Django 2 and all the good things. It was a lot of fun building it and working on it. I'm still working on it. And I think this is just a cool showcase for that also where you get some graphs in there, you get some interactive or you get some code snippets, so you can copy and paste and you get some math type setting there and I think that makes it very engaging to the reader as well. And yeah, it's just a cool topic. I'm just fascinated by those things. How you can use the wisdom of crowds or whatever that way. You can say, well, we have enough people using the platform, you have enough people watching Netflix and then all of a sudden, I can get these amazing recommendations for other things that I would have never thought about watching.
19:42 Michael Kennedy: Yeah, you help make it better for other people without even knowing it, right? Your reactions are there and used for good. Yeah, so it talks about things like K-Nearest Neighbours and probably the fundamental algorithm there that's being used.
19:54 Dan Bader: Yeah, I believe it's for this particular recommendation system technique called collaborative filtering, but there's also other approaches that I can't really speak intelligently about.
20:06 Michael Kennedy: Yeah, sure, there's even some cool recommendations like the Surprise recommender system, which is a Python scikit-learn extension. So you can install a scikit-surprise.
20:17 Dan Bader: That's a cool name for a recommender system...
20:19 Michael Kennedy: That's a great recommender, like surprise, we can actually recommend something useful. This is not wasted space here. Cool, yeah, so if people are interested, they can check that out. And also I noticed it's got this bimodal way of working with it. It says, well, if you want to use pip, here's how you do it, if you want to use conda, here's how use that as well. So this ones seems like there'd be a lot of folks using Anaconda as their Python distribution to work on this.
20:44 Dan Bader: Yeah, I think if in the data science space, Conda seems to be quite popular and so typically we standardize, for the articles, we standardize on just using pip because that's the lowest common denominator. But in this case, we felt like it makes sense to be closer to where the audience might be there.
21:02 Michael Kennedy: Right, take it to the data scientists and then make them show it in that way. That's really cool, so I love it. It's a good one. Number six on our list here.
21:11 Dan Bader: Right, so this one might be a bit surprising, but it is called Your Guide to the Python Print Function.
21:17 Michael Kennedy: This is the one that I was talking about when I thought, okay, I know this thing. And then I'm like, wait a minute, maybe I don't know this thing.
21:23 Dan Bader: So this is more like a book about the Python print function by Bartosz Zaczynski and this is just this incredible deep dive into the print function/print statement in Python 2 because again we think, okay, maybe this is a paragraph or two about what you can do with the print function. You can pass some arguments to it...
21:45 Michael Kennedy: It requires parentheses now, it didn't used to.
21:47 Dan Bader: Exactly, right, like what else is there to say? And then it goes really, really deep into the history of the print function and some common use cases that maybe you might not associate with the print function directly upon first glance. For example, how can you build a cool console user interface? How can you do colors in the terminal and how can you pretty print if you have a nested data structure like some JSON that you parsed into Dictionary? How can you make sure it actually looks good when you print it out through the console or some debug window. And so it's not just purely about the print function, but all the kinds of different best practices and ways you can make printing better in your Python programs.
22:28 Michael Kennedy: Yeah, that's cool. No one wants to try use a minified Dictionary for debugging.
22:33 Dan Bader: Nope, I usually take those and then paste them into the Black online format there. I get a nicer representation.
22:42 Michael Kennedy: Yeah, yeah, so it covers some of the things I think are actually not super obvious to new folks coming from the language.
22:50 Dan Bader: That's right.
22:51 Michael Kennedy: If you come from other languages, you might not know that you can actually use a keyword argument to set the end to be instead of a \n to be a comma and print out one line with a bunch of commas or something like that. Or the buffering, if I'm trying to do something computational and print out as the computation is happening, a lot of times, I can get buffered up and then it all shoots out at once or if you're delaying or late on something, you won't actually see all of the output. There's a bunch of little tips like that in there, right?
23:20 Dan Bader: Yeah, and like with everything, there's a deep rabbit hole.
23:24 Michael Kennedy: Yeah, down the rabbit hole you go, right?
23:26 Dan Bader: Yeah, I love this article where you think, okay, we're going to scratch the surface here a little bit and then we're done and there's all kinds of interesting other things you could do or just learn why certain things work the way they do, ANSI, escape sequences for making colors in the terminal. When you read about them, it looks like this incredibly confusing format and then you learn a bit more about the history and how it relates to these old school terminals of the old mainframe computers and how it's just a format that has grown over decades. And well, sure, we could all throw it away and maybe engineer something from scratch, but it's cool to understand if I, I don't know, boot up my Windows computer or MacBook in 2020 why it's still supporting that stuff and how it goes back 50 years.
23:26 Michael Kennedy: Yeah, well, another thing that I think makes a night and day difference for these simple little command lines apps is color. More of those should use color, right? If you're saying in the help output, it would be great to show the required argument is one color and the optional ones is another and it's incredibly easy, but if you don't to do it or you think it's hard or it's hard to do cross platform or whatever, then you won't.
23:26 Dan Bader: Yeah, oh, speaking of color there in the terminal, one of my favorite tools is the bpython REPL.
23:26 Michael Kennedy: Bpython?
23:26 Dan Bader: Bpython, so the letter b and then python, one word. It's a Python interpreter like a Python, not an interpreter, but a REPL environment that is just like when you start Python from a command line, you get your little prompt and you can type a Python code into it and run it, but it does syntax highlighting, so it'll give you beautiful colors in the terminal and it also does auto complete, which is cool. So we use that all the time in our video courses and in examples and people always ask, "What's that tool?" I want to use that tool, and it's great. The color really adds...
23:26 Michael Kennedy: It adds a lot, yeah. Maybe I think I've heard of bpython. I haven't used it, I'm all about the ptpython. Are you familiar to that? It's like Emax in the REPL, kind of taking it back to my Emax days. So last thing, we go on and on about this incredibly for a really long time about printing, but there's one thing that's in here I think that's pretty interesting that they talk about that I guess also surprised me. I didn't really think about it is mocking the print function for unit tests.
23:26 Dan Bader: Yeah, that's a surprise, but it's actually a pretty annoying problem if you want to write tests for a program where in the test you actually want to make sure it's printing the right stuff. Well, how do you do it, how can you actually redirect that output into some kind of buffer, so you can inspect it and say, okay, we got the output that we wanted?
23:26 Michael Kennedy: I called this and it said enter this or whatever, right, like the prompt that we were expecting or something. Yeah, yeah, pretty cool. Alright, well, let's move on because it is the print function, but it is actually really, really interesting and what are we up to number?
23:26 Dan Bader: I am trying to check, I think number seven. This is number seven.
23:26 Michael Kennedy: Yes, number seven, which goes right along to number eight in a sense. So How to Write Beautiful Python Code with PEP 8.
23:26 Dan Bader: Yeah, so this is a cool article by Jasmine Finer and it's about the PEP 8 style guide in a beginner friendly intro to PEP 8, why it exists, how it can help you format your code in a way that other Python developers will expect and appreciate. And I think it's a really good one because it breaks it... When you read the actual PEP 8, it can be feedback that I heard in the past was it's just very, very overwhelming to take it all in and take all the examples in, so we try to break it down and give you a good overview and then point you to the original PEP, so you can do the deep dive.
23:26 Michael Kennedy: Yeah, it's really cool and it's one of those things that's really important, so you look like you belong. If you start doing stuff that is Java style or C# style and someone says, yeah, I'm interviewing for a Python job and if you would allow me to write a little code for you and you start using camel case method names or something like that. You're like, not so sure you're a Python developer. You don't look like you're from around here.
23:26 Dan Bader: Yeah, first impressions matter, I guess.
23:26 Michael Kennedy: Yeah, and once you know the conventions, some of those conventions have meaning. The underscore has a certain meaning and things like that. And so it's not implicitly obvious from that thing what the meaning is, but once you study it, then you get to know, right?
23:26 Dan Bader: Yeah, I actually wanted to ask you is your Talk Python, is the code for the Talk Python platform, is it PEP 8 compliant or you got to make sure it is PEP 8 compliant?
23:26 Michael Kennedy: It's both for the platform it is, I would say PEP 8 compliant and I try to do that in the courses. Probably the way I do that most is just running, working on everything in PyCharm and PyCharm will highlight stuff and make it obviously... It'll as you type, it'll highlight. It'll go, no, no, no, there's just something clearly wrong. You don't have an underscore, you have camel case on a variable name, stop doing that. And so yeah, I don't run anything like Black across the whole thing. The only thing I've run entirely across the whole code base, not across the courses 'cause it's recorded, so it'd be weird to change it, but in terms of the platform, I've used Flynt. Are you familiar with Flynt?
23:26 Dan Bader: I feel like I've heard about it. Is this another auto formatter?
23:26 Michael Kennedy: It's a very special tool, but I love it. What it does is it will take all the various string formatting styles of working with strings, so percents, value value or the format something or other and so on and it turns them all to f-strings.
23:26 Dan Bader: Oh, that's cool.
23:26 Michael Kennedy: Yeah, it'll just rewrite your code, rewrite all your f-strings.
23:26 Dan Bader: I know a certain Core Python developer who would love that.
23:26 Michael Kennedy: Yeah, so I ran it and in the early days, it had a couple of bugs when you were doing numerical formatting like this number, comma, or colon, comma, like .2f, like that would get freaked out, but yeah, after a couple of iterations, it's really quite good.
23:26 Dan Bader: That's cool, I think, yeah, I got to run that. That's great.
23:26 Michael Kennedy: Yeah, so I just ran it again. It's 20,000 lines of code across the training site in the Talk Python and Python Bytes websites and I think there is maybe one mistake. So I looked at the dif before I checked them all in and just saw that actually this one out of 1,000 there's this mistake. I think actually those are probably pretty much gone, but yeah, anyway, it's not PEP 8, but it's part of a continuation.
23:26 Dan Bader: Yeah, and I think with this stuff, I feel like we've got to be clear. It can often be ambiguous. Any sort of code style guide like PEP 8 or what have you and then other languages, it's usually not... At the end of the day, naming is a big part of a developer's job, I think, and picking names that are actually communicating the intent well and other people can understand. So it's not going to solve that problem because, well, even though if you're following PEP 8 to a tee, and you're using all the upper and lower case letters in the right way and your naming just doesn't make sense, then that's also not going to be great. So it's an ongoing struggle.
23:26 Michael Kennedy: Yeah, you're doing a list comprehension and it's all on one line. It's got the n for n and such-and-such, if N such-and-such and it happens to be 79 characters long, though it's on column 79, that's fine. You don't need to wrap it, but it's super hard to understand why it would make sense to have that three lines, the select value, the loop, the collection it's going through and then the task, it would be much better. And PEP 8 doesn't say, well, if it's 79 lines and complicated, it should be broken up, but 80 lines is the hard limit and things like that. So we got to think beyond it.
23:26 Dan Bader: Are you following the 79 characters limit in any of your code bases?
23:26 Michael Kennedy: Do I follow, sometimes. There's a few times where I don't. So if I have a raw string or a multiline, not raw string, a multiline string where you do triple quote and there's a bunch of stuff and then triple quote to close it. I don't know of a way to not do more than 80 lines if what needs to be in the string is more, or 80 columns. But it will still complain to me, oh no, this line's 120. I'm like, yeah, but you show me how to fix it and then we'll have a conversation, but I can't fix this without completely going, you know what? We're going to have a string concatenation to nobody's end rather than this multiline string.
23:26 Dan Bader: Yeah, that's a tough one.
23:26 Michael Kennedy: There's a few edge cases, but I try to do.
23:26 Dan Bader: Yeah, me too, like every since I started using Black...
23:26 Michael Kennedy: Black's going to change it anyway.
23:26 Dan Bader: I think you can tell it to use a different line length limit. I feel like that's always something that comes up where it's a controversial topic where should you follow the 79 character limit. There's a 72 character limit recommendation for doc strings. I try to follow that as well. I have these little, little gutter margins set up in the editor.
23:26 Michael Kennedy: Yeah, exactly, that's cool.
23:26 Dan Bader: But then sometimes I'm thinking, okay, but wouldn't it be nice just to go 100 characters longer. So I think whatever number people pick as long as you're consistent is probably a good thing.
23:26 Michael Kennedy: Yeah, it's more contextual. This portion of Talk Python To Me is brought to you by Brilliant.org. Let me knock something off your holiday to-do list, gifts. Spread the love to your loved ones by gifting them Brilliant. This really excites me because it's such a fun way to nurture curiosity, build confidence and develop problem solving skills crucial to school, job interviews or to their career. Brilliant's thought provoking content breaks up the complexities into bite sized understandable chunks that will lead them from curiosity to mastery. Go to talkpython.fm/brilliant and grab a gift subscription to help your loved ones finish their day a little smarter this season. That's talkpython.fm/brilliant or just click the link in the show notes. We talked about PEP 8 and how about article eight?
23:26 Dan Bader: Article eight is about the Python lambda function. So it's called How to Use Python Lambda Functions by Andre Burgaud and yeah, I wanted to highlight this one because lambdas in Python are a topic that can be challenging, I think. It's something that a lot of times you don't really have to, you don't really work with and so you don't get a lot of experience working with it and then when there might be a situation where it's actually useful, for example, if you want to sort a list or something sorted by a custom key, then if you don't know about lambdas, it's going to be a frustrating experience.
23:26 Michael Kennedy: Right, like I got to write this other function and that's kind of weird. But yeah, one of the things that when you learn them, you're like, man, that is cool. I can't believe, I can think of immediately 10 places I would use this, but they're not obvious that they exist or that you could use them until you see them.
23:26 Dan Bader: Yeah, that's right and what's the quote there? The dose makes the poison. I only know the German version.
23:26 Michael Kennedy: The dose makes the poison.
23:26 Dan Bader: Yeah, basically you don't want to apply it. It's like salt. You don't want to overdo it with the salt because then the food's going to taste terrible.
23:26 Michael Kennedy: Yeah, a pinch will do you, absolutely. So yeah, that sounds about right.
23:26 Dan Bader: So this article goes into some use cases and also into the language history or why are these types of functions called lambda functions and how does this relate to this thing called Lambda Calculus that was invented in the 1930s and we'd go back into some of the computer science stuff.
23:26 Michael Kennedy: That's cool.
23:26 Dan Bader: So you can also learn about that.
23:26 Michael Kennedy: You know another thing that I think interesting that gets very little attention, I suspect this is happening to a non-trivial number of people and they don't even know is closure. So closure is the idea that I have a variable that's either available in the local method or it's a global variable. Most likely it's a local variable on that method where you're using the lambda and you say it in the function body, the lambda body, but not as an argument. It's somehow magically...
23:26 Dan Bader: Capturing that, I find this so hard to explain.
23:26 Michael Kennedy: It's so hard.
23:26 Dan Bader: Because when you see it with an example like in the article, it to me at least a lot easier to wrap my head around it, but let's give it a shot.
23:26 Michael Kennedy: Yeah, well, some really interesting stuff happens with closure. It's not just that the variable is passed, but it's remembered. It's remembered across function calls. And so even if you change it and then you call the lambda again, it will work with not the original value like a copy, but it will work with a changed value.
23:26 Dan Bader: Which can really bite you also if you're referring to a mutable object and you think you've captured the full state of this object and then it gets changed under you, which I think this is also the danger of using lambda is that if you don't understand how closures work or when that effect kicks in that you might be writing code that actually breaks under unexpected circumstances.
23:26 Michael Kennedy: Yeah and it can be incredibly hard to understand why if you have no idea that this is happening. On the flip side, you can use it for great power as well. Let's just go to something super simple. I want to sort a list, let's say key equals lambda of item, colon, do something with the item. But maybe there's other variables or other data that's in the function that you want to use to decide how you sort. Like if it's below this cutoff, I want it first, but if it's after this cutoff or somehow you've got to compute with some other data. It's not purely just the item.
23:26 Dan Bader: If you wanted to sort, you had an address book with, I don't know, name and year of birth and you wanted to sort it by some calculated value or both of them.
23:26 Michael Kennedy: Right, so if they don't have a date of birth, you could have here's the default date of birth we're going to use.
23:26 Dan Bader: Yeah, substitute something in...
23:26 Michael Kennedy: Yeah, they're all going to be born in 1970 or something, who knows. So you could have that as a local variable, but then include that in your sort lambda, but the function that's getting called, it only takes the item and the list doesn't know about your need of this other variable. It's not going to pass it in, but you can just use closure to just capture it and just bring in more arguments into your lambda than would otherwise be available and that's a super powerful thing you can do.
23:26 Dan Bader: Yeah, I think that probably the main use case what I personally use them for, there's also a section in the article that talks about whether lambdas are we can consider them Pythonic or not because in PEP 8, which we just talked about, there's actually a recommendation there that says you should always use a def statement, so define a proper function instead of an assignment statement that binds a lambda expression directly to an identifier. And so this is like a strong discouragement to using lambdas. I think mainly when you actually you want a named function. I think anytime you actually want a named function, you should probably not use a lambda. If it's a one-off thing, that's where I would use it.
23:26 Michael Kennedy: Yeah, you even talk about it in your article a little bit anonymous functions, meaning they have no name. You're passing them somewhere. You're modifying the behavior of the sort or whatever, but you're not naming the thing doing that.
23:26 Dan Bader: Yep, that's right. And with great power comes great responsibility.
23:26 Michael Kennedy: That's right, I think one of the key essence of the lambda, decide should I make a separate function or should I make a lambda function? I think one of the key differences here or the key decision at least for me is is it going to be clearer to just plunk the implementation right here than to give it a good name and put it somewhere else. So if it made a lot of sense to give it a good name and put it over there 'cause it's kind of complicated but the name tells you what it does and then use that as the sort, great do that. But if it's like I'm going to sort just by sort a list of customers, it's just lambda c: goes to c.name. Okay, it would be more confusing to move that away 'cause then you'd have to be sure sort by name, you're like, oh, wait a minute, descending or ascending? Well, they renamed it to say sort by name ascending, but then they actually changed the implementation to descending, but they forgot to rename it 'cause they were afraid to break the code and there's all sorts of weird stuff if you move it away. So if it's clearer to have it inline than lambda, otherwise not lambda, that's my take.
23:26 Dan Bader: That's a good rule of thumb. I feel like I mainly use lambdas for exactly that use case and otherwise try to stay away from them.
23:26 Michael Kennedy: If you have to line break a lambda, that's a problem.
23:26 Dan Bader: Yeah, that's maybe also a good heuristic. Yeah, you could only have... Basically you can just put an expression into it. So that's the other thing that we haven't even talked about. So they're also limited in what you can actually put into a lambda function. You can pretty much just have a single expression that would also be the result of which will also be returned as the return value of that function. And that also limits you, but of course you could use all kinds of ugly workarounds to do something that you're not really supposed to do with them.
23:26 Dan Bader: That's right. Alright, are we already at...
23:26 Michael Kennedy: Number nine, number nine.
23:26 Dan Bader: Here we go, so number nine is about Python coding interviews. So the article is called How to Stand Out in a Python Coding Interview by James Timmins. And I felt that this is an important topic and it's hopefully also something useful for you, dear listener, maybe you have a Python coding interview coming up or you're worried about when the day comes where somebody's going to grill you on your Python skills. And we put this article together to cover some common situations. There are basically some tips that you can use to showcase your deep understanding of the Python programming language.
23:26 Michael Kennedy: Yeah, you broke it into a couple of sections. You've got know your built-in functions, know the right data structure, take advantage of the standard library. If somebody says, I want you to use the quick sort, you're like, you know what? I created a list and I want to sort. Exactly or something like that, right? Or I think the data structures is super important. That's a great giveaway. I want you to get a bunch of, I don't know, say users and I want you, in memory, and I want you to look them up by ID and I want you to do that quickly. Does look up quickly happen, is that the question? Dictionary.
23:26 Dan Bader: Just yell dictionary.
23:26 Michael Kennedy: Dictionary! Exactly or unique or distinct, okay, set. Did they say distinct? They mean set, just right away you could have a complicated 10-line, four-loop where you test have you seen it before or set. That's both knowing the built-ins and knowing the right data structures, I think.
23:26 Dan Bader: Yeah and there's so much good stuff in the Python Standard Library or in the Core language. Another great one, I think, that's worth knowing about is in the collection module, the Counter class, which is if you ever need to count different items or how often does this string or this word occur.
23:26 Michael Kennedy: Right, I got a list of a whole bunch of domain names. I need to know how many each one of them appears. That sounds like a challenge or that sounds like two lines. If you know counter, right? You import collections, you create your counter, the most common, but these things are incredibly simple when you know them, but if you don't know they exist, it's really challenging. I think that's actually a problem from, not a problem, but a learning challenge going back to your other article, I don't remember which number it was, but the one, I think maybe number two about all the projects. Some of those projects would be really easy if you knew the right libraries, but if you thought, I have to write this from pure Python from scratch and I've got to implement this stuff, like, oh, that MP3 player is super hard, let me get down to the bytes and look at it. Like, no, you pip install like the MP3 library or whatever it is that works with that, right? There's a whole lot of options and I think learning Python is challenging because you learn the language and you think you've done it, but you've only hit the 10%. Now you've got to learn the standard library, then you got to learn everything on Awesome Python or PyPI. So there's these levels, but I do think for interviewing, knowing the foundational stuff is most important.
23:26 Dan Bader: I agree and we were thinking we're going to pick stuff that is actually very likely to come up in an interview because in an interview, I think you're not going to get super specific or you're not going to talk about the LMHDB or whatever the lightning in memory database that we talked about earlier. That would be... Nobody's going to expect, I mean, depending on the kind of role but...
23:26 Michael Kennedy: Right, if it's data science, they might expect you to know NumPy. If you've claimed you know Python, you better know NumPy, at least cursory.
23:26 Dan Bader: Yeah, and if you claim that, you especially better know about things like the collections module, these core things...
23:26 Michael Kennedy: Yeah, for sure. What about when you get stumped? What is your thoughts on like how do I do this thing? Like, inside you're screaming, I have no idea.
23:26 Dan Bader: I start sweating profusely and shivering That's why I'm running my own company now. Yeah, I know that's a tough one. I think the advice that I would give is start asking questions because it's oftentimes not a good sign if you ask someone a question in an interview setting and they immediately launch into writing code or they feel like they're expected to know the answer off the bat. A lot of times, what the interviewer will want to see is how are you approaching a problem, are you able to get help, are you able to ask intelligent questions and even if you don't know the specifics, nobody really expects that. A lot of times if you can use Google, if you can use Stack Overflow, if you can use Talk Python and Real Python and all these sites that are available to you, you would have that in your normal work environment. I use Google and Stack Overflow probably hundreds of times in a productive day.
23:26 Michael Kennedy: I use it shamelessly without guilt or judgment. I mean, because there's a bunch of stuff that you need to know and then there's a bunch of stuff that just doesn't deserve to take up space in your memory, and you should just be able to go, I'm just going to Google it. I don't know what the right way to do this library with that thing is, I'm going to Google it, but just actually knowing that it exists and I just don't remember quite how to use it, I think, is the big step. I know there's a Counter thing and I know I can get it to group by the count, I just don't remember the steps to make that happen. I think that's okay.
23:26 Dan Bader: Yeah, I think that's totally okay. Or just DuckDuckGo it, just Bing it, Google it, just AltaVista it, I wonder what else is there, Yahoo it.
23:26 Michael Kennedy: Yeah, AltaVista, that's a good one. I remember that, that was good. One other thing I would put out there is a huge turnoff to me if I was interviewing, I did that for awhile with people, if I feel like they are lying to me, they're done. I don't care if I say like, oh, how would you do that with SQLAlchemy? Oh, I've used so much SQLAlchemy and then you can tell they've never ever, ever seen it. They can't even describe what all would you just create a class derives, like another class thing that maps to the database. That's a foreign idea, but they're claiming they've used it in production, done.
23:26 Dan Bader: Not a good strategy.
23:26 Michael Kennedy: Not, I don't know, how do you feel? Would you hire that person? 'Cause everything else comes through the question.
23:26 Dan Bader: I agree, yeah, it's that you want to find out would you ask the interviewer, I feel like you also want to find out would you want to have this person on your team, would you want to work with them? Would I trust them to start making up stuff like did you review that pull request or did you merge that hot fix or I don't know, do that and then you feel like you can't really rely on that person, then that's not a good start.
23:26 Michael Kennedy: Yeah, or we're going to build an eCommerce backend, who's done payment stuff before and feels like they can do it?
23:26 Dan Bader: Definitely use floats for currency. I don't know if we have that one in the list, but that's also a really common question, I feel like where people are like, oh, what data type should you use to represent currency in your program?
23:26 Michael Kennedy: Integers, probably.
23:26 Dan Bader: Yeah, and then break it down to cents and then use integers.
23:26 Michael Kennedy: Just round it. About a dollar. It's all good, it's about a dollar. Alright, well, we're coming up on the grand finale here and this is another one that I'm very passionate about, I could riff on for a long time. So you'll have to stop me at some point, but it has to do with the object oriented programming component of Python.
23:26 Dan Bader: Yeah, so the article is called Inheritance and Composition: A Python OOP Guide by Isaac Rodriguez and I think inheritance and composition, that is one of the core pieces of object oriented programming. And in my experience, it's also the piece that if you're completely new to OOP and you're trying to understand, okay, well how is this helpful, how does this work, it can be a sticking point for some people, so we wanted to do a dedicated article that is basically a deep dive on inheritance.
23:26 Michael Kennedy: It sounds a little bit like modeling with objects and just some practices around that.
23:26 Dan Bader: Right, yeah, how do you go about breaking down a hierarchy, I guess, a domain into a hierarchy of objects.
23:26 Michael Kennedy: Yeah, exactly, I was just getting that. And so maybe we should define inheritance and composition. I think inheritance is pretty clear. Composition might be a little less well-known. So inheritance is I want to model a bunch of cars, so I have a basic car or just a car, but then I have a sports car that does sporty things. Maybe it has paddle shifters or it has a manual transmission mode that has additional functionality. So I might say, well, the idea is what we're going to do is we're going to create a car and a sports car and then maybe I want to have a track car that can also take specs that solely derives from a sports car. And the deeper that those get, the more full of the abstractions can break down pretty hard. If you model creatures, I've got a living animal and then I've got a bird and then I've got what do you do with a robot bird? Does it derive from bird? It has bird-like things but the animal eats, robot doesn't eat. So if you go too deep, it's a problem, right? So that's inheritance obviously. Composition, tell us about it.
23:26 Dan Bader: Composition, so if inheritance defines is a relationship, so like a sports car is a car and a car is a vehicle and a vehicle is a thing or whatever, a machine, composition defines a has a relationship. So you can say okay, a car has an engine or a car has a steering wheel...
23:26 Michael Kennedy: Right and has a transmission. Instead of making it a sports car, maybe you can just make a car with a sporty transmission. And so the whole thing doesn't have to... Because I don't know, what if you have some kind of truck but it also has a manual shifting thing. You wouldn't have a truck derived from a sports car. That would be weird, but you could easily interchange the parts and it helps really alleviate some of those deep object hierarchies, I think.
23:26 Dan Bader: Yeah, it's basically another tool in your tool box there for defining these relationships because if you define everything in terms of an inheritance relationship, then you end up with these unmaintainable, you end up on the dark side of OOP.
23:26 Michael Kennedy: And small changes to a deep down base class can make absurd things in the end, like the robot that has to eat or something like that 'cause maybe it didn't eat at first and that made sense, but now, later you realize all the animals have to eat and then, well, what do you do about the robot thing that we put there?
23:26 Dan Bader: That's where you use multiple inheritance. That's a whole nother can of worms there.
23:26 Michael Kennedy: That's a big can of worms as well. For sure, but I'm a big fan of composition. I think, I can't remember where I heard, I'm pretty sure the original Gang of Four Design Patterns book said prefer composition over inheritance.
23:26 Dan Bader: Yeah, you want shallow hierarchies.
23:26 Michael Kennedy: Yeah, objects in inheritance aren't inherently bad, but they're easy to abuse. And so composition is a really good way to keep those shallow and interchangeable and small. So yeah, way cool, I like this one a lot.
23:26 Dan Bader: Wow, did we really make it all the way? Well, actually speaking of the Gang of Four book, I think that might be a recommendation here at the end of the article because we try...
23:26 Michael Kennedy: Recommended reading, yeah, so the article comes with recommended reading, right? Yeah. It's got some cool design patterns, Head First Design Patterns, Clean Code, SOLID Principles, Liskov Substitution Principle, all those kind of things. Yeah, a lot of these apply. It would be remiss of us, I think, to riff so fondly on an object oriented story in Python without saying that a lot of what people do with objects and classes in other languages is simply unnecessary in Python. So there is a little bit of pushback. Well, I know you did Java and everything had to be a class, you don't have to build it this way. For example, if you have a variable that you need to be basically a singleton and then you want to group a bunch of functions together, you could have a static class that has those in there in Java or C# or something like that, but you could also in Python just have a module that has a variable and it has functions and then if you just import that module, you say that module.the field or the variables or the functions, that's the same thing as a static class.
23:26 Dan Bader: Right, and it saves you a bunch of work and it's more Pythonic, I guess, than making everything a class.
23:26 Michael Kennedy: Yeah, so maybe there's a little bit of, do I really need a class for that? If you're going to create different ones of them, they're going to have different values at the same time. Well, probably, right. But maybe if you're just trying to group stuff, maybe the module's the right thing. But if you do decide and it does make sense to have a class, this inheritance versus composition thing is super important to understand.
23:26 Dan Bader: Yeah, absolutely and I don't want to give the impression that if you're writing in an object oriented programming style that that somehow is superior or the end all of coding, I don't think that's actually true. I think the really powerful thing is understanding these tools, to have a really big tool box and being able to pick the things that make the most sense. A lot of times when I'm writing a program in Python or I'm sketching something out, I'll hardly write any classes depending on the use case or I found myself most recently just basically adding these. So I've been working on the Real Python platform a lot and I've been writing more function based codes or procedural code where maybe my data model is class based, but then I'll have a module where, I don't know, redeeming access codes or coupon codes or something like that and it basically defines a really nice high level interface to me...
23:26 Michael Kennedy: Right, these are the five operations you do on coupons or something, right?
23:26 Dan Bader: Yeah and that's all function based. And then internally, they use classes to represent the data and shuffle it around...
23:26 Michael Kennedy: Right, probably working with Django ORM or something like that, right?
23:26 Dan Bader: Yeah, instead of cramming that all into a view or actually I prefer for example function based views in Django instead of class based views because I don't like getting the deeper indentation. We could get into all kinds of...
23:26 Michael Kennedy: Yeah, the whole indentation's another story, yeah.
23:26 Dan Bader: There's disagreements there, but yeah, just want to make sure that I get this across that I don't think the OOP coding style is...
23:26 Michael Kennedy: Is not the one true way.
23:26 Dan Bader: The one true way, there should be exactly one way to do things in Python.
23:26 Michael Kennedy: Yeah, but if you're going to do it, understanding this difference between inheritance and composition certainly makes sense. I do a lot of what you're recommending there as well. Alright, well, that's our top 10.
23:26 Dan Bader: Yeah, that went by super fast.
23:26 Michael Kennedy: Yeah, it did go by fast, but I think these all have special value and people might be kicking back. A lot of folks have vacation time around this time of year. They're also thinking of what's coming in the next year in 2020. I mean, first of all, let's just take a moment and say thank you, Python 2, but goodbye.
23:26 Dan Bader: Yep, bye-bye. We'll miss you.
23:26 Michael Kennedy: The death clock is down to single digit days probably at this point. So that's actually pretty exciting.
23:26 Dan Bader: Yeah, that's a big change, right? Yeah, you're right.
23:26 Michael Kennedy: Yeah, cool, alright, well, there's a bunch of articles for people to check out while they're on vacation, got some time away from work, they don't have to fill out TPS reports all day.
23:26 Dan Bader: Smash that printer.
23:26 Michael Kennedy: That's right, smash that printer. Awesome, alright, well, thanks for being here as always.
23:26 Dan Bader: Yeah, thanks for inviting me, it was great.
23:26 Michael Kennedy: You're welcome. I guess I should ask you the two questions before you go. So the two questions are, what editor do you use to write Python code these days?
23:26 Dan Bader: So I've started to use Visual Studio Code a lot. I've used Sublime Text.
23:26 Michael Kennedy: Yeah, it's a pretty similar style of editor...
23:26 Dan Bader: Very similar, what I still love about Sublime is just how fast it is. There's a noticeable difference in the rendering speed in scrolling around, but the Python integration that VS Code has out of the box is pretty cool.
23:26 Michael Kennedy: It's growing and growing all the things it can do.
23:26 Dan Bader: I like it for recording video courses because I can have an integrated show that I can have a setup that looks really, really nice, I think. So I've been doing that a lot recently. And so yeah, working out of VS Code.
23:26 Michael Kennedy: Yeah, awesome. The other question, changing for today, what's next for Real Python in 2020, 100 authors?
23:26 Dan Bader: Yeah, that's a big goal of mine. I would love to have 100 authors published on the site, authors and instructors as a magical number and maybe we'll crack that 3 million visitors. I don't know how many Python developers are out there.
23:26 Michael Kennedy: Well, I suspect after they listen to this episode, it'll probably be 3 million straight up.
23:26 Dan Bader: It'll be 10 more. For sure, yeah.
23:26 Michael Kennedy: Awesome, well, best of luck in 2020 and keep up the good work. It's a huge resource for everyone.
23:26 Dan Bader: Thank you, I mean, same to you. It's been so cool just becoming friends with you and when we first met, which I think was three years ago...
23:26 Michael Kennedy: Three or four years ago, it's quite awhile back.
23:26 Dan Bader: And just being on this journey here together, I really appreciate that.
23:26 Michael Kennedy: Yeah, absolutely, thank you, same to you. It's been fun to be on it together.
23:26 Dan Bader: Awesome, man.
23:26 Michael Kennedy: Alright. Well, catch you later, bye.
23:26 Dan Bader: Yeah, bye-bye.
23:26 Michael Kennedy: This has been another episode of Talk Python To Me. Our guest on this episode was Dan Bader and it's been brought to you by Linode and Brilliant.org. Start your next Python project on Linode's state-of-the-art cloud service. Just visit talkpython.fm/linode. You'll automatically get a $20 credit when you create a new account. Brilliant.org encourages you to give the gift of critical thought and knowledge. Visit talkpython.fm/brilliant and grab a gift subscription to help your loved ones finish their day a little smarter this season. Want to level up your Python? If you're just getting started, try my Python Jumpstart by Building 10 Apps course or if you're looking for something more advanced, check out our new Async course that digs into all the different types of async programming you can do in Python. And of course, if you're interested in more than one of these, be sure to check out our Everything Bundle. It's like a subscription that never expires. Be sure to subscribe to the show. Open your favorite podcatcher and search for Python, we should be right at the top. You can also find the iTunes feed at /itunes, the Google Play feed at /play and the direct RSS feed at /rss on talkpython.fm. This is your host, Micheal Kennedy. Thanks so much for listening. I really appreciate it. Now, get out there and write some Python code.