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.

