WEBVTT

00:00:00.001 --> 00:00:04.620
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.

00:00:04.620 --> 00:00:11.160
This is episode 242, reported July 14th, 2021. I'm Michael Kennedy.

00:00:11.160 --> 00:00:12.180
And I'm Brian Okken.

00:00:12.180 --> 00:00:13.500
Hi, and I'm Al Swigert.

00:00:13.500 --> 00:00:23.400
Hey, Al. Welcome, welcome. Before we get to introduction with you, I just want to say this is brought to you by our courses over at Talk Python Training and Brian's book.

00:00:23.400 --> 00:00:27.720
But first, let's just hear about you, Al. Tell people who you are if they don't know.

00:00:27.720 --> 00:00:36.660
Hey, I'm Al Swigert. I'm mostly known as the author of Automate the Boring Stuff with Python and a bunch of other Python and programming books for beginners.

00:00:36.660 --> 00:00:42.440
So all my books are released under a Creative Commons license, so it's free to download and share them.

00:00:42.440 --> 00:00:45.200
You can get them at inventwithpython.com.

00:00:45.200 --> 00:00:45.520
Nice.

00:00:45.520 --> 00:00:50.900
Yeah, yeah, fantastic. I would say the Automate the Boring Stuff has certainly been well received.

00:00:50.900 --> 00:00:51.900
Yeah.

00:00:51.900 --> 00:00:54.200
I hear it quoted a lot, for sure.

00:00:54.200 --> 00:00:55.880
Brian, do you want to get us started or what?

00:00:55.880 --> 00:00:57.560
Yeah, I'll just get us started.

00:00:57.560 --> 00:01:08.860
So, no, so Just, I saw a tweet by Jeff Triplett that mentioned Just as a replacement for Make, so I needed to check it out.

00:01:08.860 --> 00:01:10.540
So, and it's like super cool.

00:01:10.540 --> 00:01:16.540
Make, for people who don't know, is a thing that you can type, basically you type Make, and then it automates a bunch of commands.

00:01:16.540 --> 00:01:23.320
Like if you've got a seriously complicated build link process, it could be embedded into a Make file, and then you just type Make, and that happens, right?

00:01:23.320 --> 00:01:24.120
Right, right.

00:01:24.120 --> 00:01:28.980
And it's, I don't know what the history of Make really is, but I used it a long time.

00:01:28.980 --> 00:01:44.500
I've been using it for decades for, one of the things it does well is convert, like if you've got, take all your .c files and convert them to .o files, and then combine your .o files, and all the build process for the C tool chain.

00:01:44.500 --> 00:01:47.340
But you can do it for, you can really do it with any language.

00:01:47.340 --> 00:01:49.820
But people have like abused it, and so have I.

00:01:49.820 --> 00:01:57.200
Even Python projects often use Make files, because Make is often around on Unix-like environments.

00:01:57.200 --> 00:02:04.580
And so having Make file around, you can use it just sort of to automate some of your common tasks, like make release or something.

00:02:04.840 --> 00:02:10.480
To push your, to do all the commands you need to do to do a new release of a project or something.

00:02:10.480 --> 00:02:12.180
But there's problems with it.

00:02:12.180 --> 00:02:15.960
And so Just is a replacement for it.

00:02:15.960 --> 00:02:21.860
And it's written in Rust, so it's pretty fast and clean.

00:02:21.860 --> 00:02:23.880
Well, actually, I don't know if it's clean.

00:02:23.880 --> 00:02:24.980
I haven't looked at the source code.

00:02:24.980 --> 00:02:27.120
But it's really easy to use.

00:02:27.120 --> 00:02:28.920
It's not C, it's got to be better.

00:02:29.260 --> 00:02:31.440
It kind of looks like mail files.

00:02:31.440 --> 00:02:32.480
So, yeah.

00:02:32.480 --> 00:02:37.040
I went ahead and installed it both on a Mac and Windows today to try it out.

00:02:37.040 --> 00:02:44.020
One of the things I really love about it is, it's not, the main part of it is to try to automate commands.

00:02:44.020 --> 00:02:54.200
It's not about, you can build like, you can use it to build things and have recipes to make all your .c files into .o files if you want.

00:02:54.200 --> 00:02:58.860
But the real power is to use it in the way we've been abusing Make before.

00:02:58.860 --> 00:03:01.340
Because you can do some cool things.

00:03:01.340 --> 00:03:13.020
Like, one of the problems with Make always has been the rules have to be on the, or the recipes have to be defined on the left column, leftmost column.

00:03:13.020 --> 00:03:17.320
And then you have to like have a tab for the commands.

00:03:17.460 --> 00:03:24.960
Well, I mean, often I have my editor set up except for Make files to replace tabs with spaces.

00:03:24.960 --> 00:03:28.120
Just works just fine with spaces.

00:03:28.120 --> 00:03:29.240
I love that.

00:03:29.240 --> 00:03:35.140
And also you can pass commands, pass arguments to commands, command lines, stuff like that.

00:03:35.140 --> 00:03:36.300
That's cool.

00:03:36.640 --> 00:03:37.320
It's super cool.

00:03:37.320 --> 00:03:42.500
One of the neat things, I don't know where it is in the documentation here.

00:03:42.500 --> 00:03:44.760
Oh, you can use arbitrary languages.

00:03:44.760 --> 00:03:49.700
You can even do like a Python command within the Just file.

00:03:49.700 --> 00:03:51.060
So it's a...

00:03:51.060 --> 00:03:51.340
That's cool.

00:03:51.340 --> 00:03:53.440
You can do some neat things.

00:03:53.440 --> 00:03:54.340
Or parole or whatever.

00:03:54.340 --> 00:03:57.760
For people listening, you basically declare the languages you want to use.

00:03:57.760 --> 00:04:04.060
And then you can implement code, like print or console.log for JavaScript or whatever.

00:04:04.060 --> 00:04:04.700
Right.

00:04:04.700 --> 00:04:10.800
This actually seems like a bad example because it's actually listing the recipe name as the language name.

00:04:10.800 --> 00:04:11.820
And you don't have to do that.

00:04:11.820 --> 00:04:14.020
So this Python here could just be foo or something.

00:04:14.020 --> 00:04:15.000
Oh, I see.

00:04:15.000 --> 00:04:17.940
So the thing that's important is the shebang.

00:04:18.360 --> 00:04:18.560
Yep.

00:04:18.560 --> 00:04:23.660
The shebang tells just which language to use.

00:04:23.660 --> 00:04:25.040
So this is pretty neat.

00:04:25.040 --> 00:04:26.980
I've started using it right away.

00:04:26.980 --> 00:04:28.860
And I think I'm going to keep using it.

00:04:28.860 --> 00:04:29.360
It's great.

00:04:29.360 --> 00:04:31.620
Well, one thing that I got out of this that's interesting.

00:04:31.620 --> 00:04:33.840
Scroll down to where it has like the how to get it.

00:04:33.840 --> 00:04:35.540
You'll see like a whole bunch of links.

00:04:35.540 --> 00:04:37.040
If you go down that page.

00:04:37.040 --> 00:04:38.180
A little more.

00:04:38.180 --> 00:04:38.780
Keep going.

00:04:38.780 --> 00:04:39.580
Installation.

00:04:39.580 --> 00:04:40.940
Yeah, I think so.

00:04:40.940 --> 00:04:41.880
There's a section.

00:04:41.880 --> 00:04:42.380
Oh, no.

00:04:42.380 --> 00:04:42.800
Oh, yeah.

00:04:42.800 --> 00:04:43.100
There you go.

00:04:43.100 --> 00:04:44.320
There's a bunch of...

00:04:44.320 --> 00:04:47.340
It shows you all these different package managers that'll give it to you.

00:04:47.380 --> 00:04:49.500
So if you want to get it from Rust, you can use Cargo.

00:04:49.500 --> 00:04:51.800
On a macOS, there's Homebrew and Mac ports.

00:04:51.800 --> 00:04:56.560
If you want it on Windows, they interestingly recommend Scoop, which I've never used.

00:04:56.560 --> 00:04:57.640
I've only used Proclity.

00:04:57.640 --> 00:04:59.000
So I don't know.

00:04:59.000 --> 00:05:02.420
I feel like there's like ice cream themes or something for the Windows world.

00:05:02.420 --> 00:05:03.960
But yeah, those are pretty interesting.

00:05:03.960 --> 00:05:08.200
I was going to be snarky and say, do you require Make to install Just?

00:05:08.200 --> 00:05:10.700
Yeah.

00:05:10.700 --> 00:05:17.360
So I got no problem using Brew install for on my Mac, but I'm not going to install Scoop.

00:05:17.360 --> 00:05:18.020
for Windows.

00:05:18.020 --> 00:05:20.600
I don't have any other need for it.

00:05:20.600 --> 00:05:22.580
So there is prebuilt binary.

00:05:22.580 --> 00:05:25.080
So I just used the prebuilt binary for Windows.

00:05:25.080 --> 00:05:26.060
It worked fine.

00:05:26.060 --> 00:05:32.460
Yeah, this looks really great because my experience with Make has been to just run the basic make

00:05:32.460 --> 00:05:33.520
command to build something.

00:05:33.520 --> 00:05:35.020
And if it works, that's great.

00:05:35.120 --> 00:05:45.560
And if it doesn't, I have no idea what to do because I feel like my knowledge of Make is sort of like my knowledge of CSS, where it's just been built up from little bits of knowledge over the years.

00:05:45.560 --> 00:05:49.660
And I've never formally sat down and read through all the documentation.

00:05:49.660 --> 00:05:54.240
100% JIT learning, like just enough time that you needed.

00:05:54.240 --> 00:05:55.720
Yeah, exactly.

00:05:56.280 --> 00:05:56.540
Yeah.

00:05:56.540 --> 00:06:00.940
Like, I actually have never really understood why phony targets were needed.

00:06:01.620 --> 00:06:12.720
And this discussion in the readme of this, of Just actually talks about why phony is needed in the first place for make files and why you don't need them for Just.

00:06:12.720 --> 00:06:14.480
So it's kind of interesting.

00:06:14.900 --> 00:06:15.780
Yeah, very cool.

00:06:15.780 --> 00:06:16.260
Very cool.

00:06:16.260 --> 00:06:18.340
We'll move on to the next item.

00:06:18.340 --> 00:06:20.800
A couple of comments for Al out there.

00:06:20.800 --> 00:06:21.100
Teddy.

00:06:21.100 --> 00:06:23.980
Hey, Teddy in the live stream says, love to automate the boring stuff.

00:06:23.980 --> 00:06:25.500
How we learn Python.

00:06:25.500 --> 00:06:28.500
Dean says, always recommend it to get started.

00:06:28.500 --> 00:06:29.120
Great fan.

00:06:29.120 --> 00:06:30.360
So, yeah, that's pretty cool.

00:06:30.360 --> 00:06:30.940
Awesome.

00:06:30.940 --> 00:06:31.560
Hey, thanks.

00:06:31.560 --> 00:06:33.520
I always love hearing that.

00:06:33.520 --> 00:06:34.820
You bet.

00:06:34.820 --> 00:06:35.380
All right.

00:06:35.380 --> 00:06:38.720
I love to hear from our fans of the show.

00:06:38.980 --> 00:06:51.320
And so Roman Wright, who worked on Beanie, the, I believe, Pydantic-based model query for ODM for MongoDB, recommended something else.

00:06:51.320 --> 00:06:55.240
This time we already covered Beanie, something called strong typing.

00:06:55.240 --> 00:06:57.500
So this is a decorator.

00:06:57.500 --> 00:06:58.780
This is from Felix the Sea.

00:06:58.780 --> 00:07:03.320
It's a decorator which checks whether a function is called with the correct arguments.

00:07:03.820 --> 00:07:09.020
So if somebody goes and puts type annotations on their code, that's cool.

00:07:09.020 --> 00:07:14.380
The editors like PyCharm will say, you're doing it wrong when you're doing it wrong.

00:07:14.380 --> 00:07:17.680
Or they'll give you autocomplete and information on the arguments and so on.

00:07:17.680 --> 00:07:20.560
But, you know, Python, that's like a hint, right?

00:07:20.560 --> 00:07:22.480
Called type hints often.

00:07:22.480 --> 00:07:23.640
Because it's a hint.

00:07:23.640 --> 00:07:24.900
It is not a requirement.

00:07:24.900 --> 00:07:32.120
And so if you want to make sure that certain types match up, basically, you can use this decorator.

00:07:32.440 --> 00:07:33.980
And there's not a lot to this one.

00:07:33.980 --> 00:07:36.180
But go over to the read the docs.

00:07:36.180 --> 00:07:39.180
There's a stay strong little character there.

00:07:39.180 --> 00:07:45.820
But the idea is if you had this thing that was like a multiplier, took an a int and a b int, you could pass other stuff.

00:07:45.820 --> 00:07:57.500
But if you pass, like if you could pass like three and four to multiply, but if you pass like hello world, it's just going to try string times string, which there's probably a cool Watt outcome that we could get there.

00:07:57.500 --> 00:07:59.420
But that's not what happens in Python.

00:07:59.420 --> 00:08:00.820
We get a type error, right?

00:08:01.060 --> 00:08:05.420
If you do a string times a number, you get a pretty interesting outcome.

00:08:05.420 --> 00:08:06.680
And this is something of a Watt.

00:08:06.680 --> 00:08:12.100
If you do like hello times four, you get hello, hello, hello, hello four times, which has always been weird.

00:08:12.100 --> 00:08:14.560
When I learned you can multiply strings, it kind of freaked me out.

00:08:14.560 --> 00:08:15.820
But I've come to find it useful.

00:08:15.820 --> 00:08:17.240
So what do people do?

00:08:17.240 --> 00:08:19.260
Well, they're like, well, this won't stand.

00:08:19.260 --> 00:08:20.580
We need to check the type.

00:08:20.800 --> 00:08:27.280
So we're going to say if is instance the first parameter and an int and is instance the second one.

00:08:27.280 --> 00:08:27.820
We can do it.

00:08:27.820 --> 00:08:29.140
Otherwise, we're going to report an error.

00:08:29.140 --> 00:08:29.920
Don't do that.

00:08:29.920 --> 00:08:35.120
Instead, what you can do is you can use this match typing decorator.

00:08:35.160 --> 00:08:41.220
And you can just say at match typing and it's going to take the arguments based on the type

00:08:41.220 --> 00:08:42.560
hints and validate them.

00:08:42.560 --> 00:08:44.300
So if you pass in the right one, great.

00:08:44.300 --> 00:08:45.200
It'll give you an answer.

00:08:45.200 --> 00:08:51.440
If you pass in something that does not match the type annotations described, it'll say it'll

00:08:51.440 --> 00:08:53.300
raise a type mismatch exception.

00:08:53.700 --> 00:08:54.980
And this can be nested down.

00:08:54.980 --> 00:09:01.860
So for example, one of the examples is it takes a list and let's see, takes a list, which

00:09:01.860 --> 00:09:04.460
is a union of strings, ints, and tuples.

00:09:04.460 --> 00:09:11.180
So if you give it a list that has either a string, int, or a tuple mixed heterogeneously

00:09:11.180 --> 00:09:13.140
into the arguments, it'll take that just fine.

00:09:13.140 --> 00:09:17.820
But if you give it some other type, like a list that happens to contain one of the elements

00:09:17.820 --> 00:09:19.520
as a date time, it'll give you this exception.

00:09:19.520 --> 00:09:21.680
So it's not just, oh, it took a list.

00:09:21.680 --> 00:09:27.100
It has, you know, like the transitive sort of property of analyzing the types is validated

00:09:27.100 --> 00:09:27.360
there.

00:09:27.360 --> 00:09:28.520
So pretty interesting.

00:09:28.520 --> 00:09:29.060
What do you two think?

00:09:29.060 --> 00:09:29.560
Yeah.

00:09:29.560 --> 00:09:34.940
So the difference between this and something like mypy is that this operates at runtime,

00:09:34.940 --> 00:09:35.420
right?

00:09:35.420 --> 00:09:36.020
Right.

00:09:36.020 --> 00:09:36.460
Exactly.

00:09:36.460 --> 00:09:38.420
Because you could do all the mypy stuff you want.

00:09:38.420 --> 00:09:41.880
And if people don't run it, well, you're not going to get any information out of it,

00:09:41.880 --> 00:09:42.080
right?

00:09:42.080 --> 00:09:42.400
Yeah.

00:09:42.400 --> 00:09:45.740
That was something that I was really surprised to learn when I first learned type hinting was

00:09:45.740 --> 00:09:51.580
that really Python's type hints don't really affect the runtime code.

00:09:51.580 --> 00:09:52.380
at all.

00:09:52.380 --> 00:09:55.880
It's just set up for static source code checkers like mypy.

00:09:55.880 --> 00:10:01.020
So it doesn't turn Python magically into a statically typed language.

00:10:01.020 --> 00:10:04.560
It's just for these static source tools.

00:10:04.560 --> 00:10:05.540
Yeah, exactly.

00:10:05.540 --> 00:10:06.660
That's mypy is.

00:10:06.660 --> 00:10:09.280
And this is kind of the other side of that, right?

00:10:09.280 --> 00:10:11.160
This is the runtime one.

00:10:11.160 --> 00:10:15.680
So maybe you would use this in the case where you're building a package or library and it's

00:10:15.680 --> 00:10:20.240
you've done everything correctly, but someone else is consuming it potentially incorrectly

00:10:20.240 --> 00:10:24.060
and you can't control whether the world uses mypy or not, right?

00:10:24.060 --> 00:10:24.280
Yeah.

00:10:24.280 --> 00:10:25.440
You just wrote a library.

00:10:25.620 --> 00:10:30.420
And so you could use this on say the boundary of your library, not everywhere, just on the

00:10:30.420 --> 00:10:33.560
boundary to make sure the stuff that goes in and out is valid.

00:10:33.560 --> 00:10:37.240
And this would be really helpful for stuff that I work on because usually I'm just sort

00:10:37.240 --> 00:10:40.920
of writing code ad hoc that sort of does this runtime checking.

00:10:40.920 --> 00:10:46.360
But it's really nice that I could just throw in a function decorator and just add that capability

00:10:46.360 --> 00:10:48.500
and that's all I have to do.

00:10:48.500 --> 00:10:49.460
Yeah, absolutely.

00:10:49.460 --> 00:10:50.140
Oh man, yeah.

00:10:50.140 --> 00:10:51.360
Yeah, this is great.

00:10:51.360 --> 00:10:55.380
Well, so clearly this is adding code, your code, right?

00:10:55.380 --> 00:10:58.620
So I'm just curious about the performance.

00:10:58.620 --> 00:10:59.220
Yeah.

00:10:59.220 --> 00:10:59.820
So is Teddy.

00:10:59.820 --> 00:11:03.740
He out there in the live stream asked, do you know if there's any potential lost performance

00:11:03.740 --> 00:11:04.820
since it's running at runtime?

00:11:04.820 --> 00:11:09.000
I'm going to say I am certain there is lost performance.

00:11:09.000 --> 00:11:15.260
Unfortunately, in Python, calling a function is a relatively slow operation.

00:11:15.820 --> 00:11:18.580
And doing a decorator is effectively calling a function.

00:11:18.580 --> 00:11:19.800
So it's got to be slower.

00:11:19.800 --> 00:11:24.060
That's why I would say put it just on the boundaries, you know, something like that.

00:11:24.060 --> 00:11:28.060
But I mean, the alternative is if you actually want to do these tests, if you actually want

00:11:28.060 --> 00:11:34.380
to do that validation, it's an if statement and multiple is instance of all over the plate,

00:11:34.380 --> 00:11:34.560
right?

00:11:34.560 --> 00:11:37.240
So if you're going to do that validation anyway, you're already calling.

00:11:37.240 --> 00:11:38.340
It's just not on the outside.

00:11:38.340 --> 00:11:39.620
It's on the inside, right?

00:11:39.620 --> 00:11:41.200
So good question.

00:11:41.200 --> 00:11:41.680
I don't know.

00:11:41.680 --> 00:11:42.460
Yeah.

00:11:42.460 --> 00:11:44.760
Another question from Ben Lindsay.

00:11:44.900 --> 00:11:48.300
Do you know how this compares with Pydantic's validate arguments decorator?

00:11:48.300 --> 00:11:53.400
I don't know, but I'm a big fan of Pydantic and the validate arguments decorator is exactly

00:11:53.400 --> 00:11:56.240
the same type of thing that we're talking about.

00:11:56.240 --> 00:11:59.580
So for example, like you should put the at validate arguments.

00:11:59.720 --> 00:12:03.880
The thing is that I did notice somewhere that, yeah, here it is.

00:12:03.880 --> 00:12:07.500
Like this validate arguments decorator is in beta for whatever that means.

00:12:07.500 --> 00:12:11.080
It won't be concrete until V2 Pydantic.

00:12:11.080 --> 00:12:18.260
But that may well be more, more concrete and more formalized than this one.

00:12:18.260 --> 00:12:18.500
Right.

00:12:18.500 --> 00:12:20.440
Although this is more standalone, right?

00:12:20.440 --> 00:12:21.480
You don't necessarily.

00:12:22.060 --> 00:12:24.700
It feels like a little tiny thing that you just plug in on there.

00:12:24.700 --> 00:12:26.040
Pydantic is doing a lot.

00:12:26.040 --> 00:12:27.300
I'm a fan of Pydantic.

00:12:27.300 --> 00:12:28.080
So yeah.

00:12:28.080 --> 00:12:28.960
Good question, Ben.

00:12:28.960 --> 00:12:29.680
All right.

00:12:29.680 --> 00:12:30.940
Al, you got the next one, right?

00:12:30.940 --> 00:12:31.900
Yeah.

00:12:31.900 --> 00:12:34.640
So I have a new book out.

00:12:34.640 --> 00:12:36.560
It just came out at the end of June.

00:12:36.560 --> 00:12:39.800
It's called The Big Book of Small Python Projects.

00:12:39.920 --> 00:12:46.320
So a lot of my books have been for people who are total beginners or relatively new to not

00:12:46.320 --> 00:12:48.400
just Python, but to programming in general.

00:12:48.400 --> 00:12:50.260
Generally people who have boring stuff.

00:12:50.260 --> 00:12:50.920
Yes.

00:12:50.920 --> 00:12:51.700
Yes.

00:12:51.700 --> 00:12:53.080
Oh, man.

00:12:53.080 --> 00:12:54.600
So much boring stuff.

00:12:54.600 --> 00:12:58.100
Actually, you have books on games and things as well.

00:12:58.100 --> 00:12:58.620
Yeah.

00:12:58.620 --> 00:12:58.980
Yeah.

00:12:58.980 --> 00:13:04.340
That's the two approaches I have to tricking people into learning how to program is getting

00:13:04.340 --> 00:13:07.600
away from Excel and then also learning how to make video games.

00:13:08.600 --> 00:13:11.580
Seems to be really common pathways into programming.

00:13:11.580 --> 00:13:17.380
So I've also noticed that with a lot of beginner tutorials, people learn the syntax and they

00:13:17.380 --> 00:13:20.400
learn all the concepts like loops and variables and things like that.

00:13:20.400 --> 00:13:25.420
But when it comes to actually working on their own projects, they're sort of stuck and they're

00:13:25.420 --> 00:13:30.520
just left staring at a blank editor and not really knowing how to proceed from there.

00:13:30.520 --> 00:13:35.840
And a lot of people will give them usually the two bits of advice that people get are, oh,

00:13:35.840 --> 00:13:40.020
you should work on open source projects or just read the code for open source projects,

00:13:40.020 --> 00:13:45.200
which is actually pretty terrible advice for beginners because a lot of open source projects

00:13:45.200 --> 00:13:46.800
might not be well documented.

00:13:46.800 --> 00:13:50.000
They're written for professional software engineers.

00:13:50.000 --> 00:13:52.400
There's a lot of concepts.

00:13:52.440 --> 00:13:52.520
Yeah.

00:13:52.520 --> 00:13:56.960
There's a huge difference between something that is absolutely polished and meant to be

00:13:56.960 --> 00:13:59.120
used in many situations in the real world.

00:13:59.120 --> 00:14:03.560
Like you might learn a lot by looking at Django, but most of the time you'll probably just be

00:14:03.560 --> 00:14:03.960
confused.

00:14:03.960 --> 00:14:05.320
You're like, why is this so complicated?

00:14:05.320 --> 00:14:10.600
Well, it's so complicated because, you know, a million websites use it in weird ways and that's

00:14:10.600 --> 00:14:11.280
why it's complicated.

00:14:11.280 --> 00:14:13.280
That's not a good learning tool per se.

00:14:13.680 --> 00:14:13.840
Yeah.

00:14:13.840 --> 00:14:18.040
Especially for someone who just learned about, you know, how to call functions and how to create

00:14:18.040 --> 00:14:20.000
classes and pretty basic things like that.

00:14:20.000 --> 00:14:26.980
So I spent, I think, I think I was working on this on and off again for about two or three years,

00:14:26.980 --> 00:14:32.780
but I wanted to create a collection of small little programs, mostly like games or puzzles

00:14:32.780 --> 00:14:38.920
or little simulations or things like that, where they were all just really simple and easy for

00:14:38.920 --> 00:14:43.000
beginners to read through and then they can understand, oh, this is how all of these concepts

00:14:43.000 --> 00:14:46.600
I learned get applied to an actual program that does something.

00:14:46.600 --> 00:14:48.000
So these aren't code snippets.

00:14:48.000 --> 00:14:50.740
They're not just like tiny little functions or things like this.

00:14:50.740 --> 00:14:56.860
This is programs that you can actually copy the code yourself and then figure out how they

00:14:56.860 --> 00:14:57.180
work.

00:14:57.180 --> 00:15:00.640
So I have about 81 of these projects altogether.

00:15:00.640 --> 00:15:08.600
They're all under, I set a limit of 256 lines of code, just as an arbitrary power of eight to

00:15:08.600 --> 00:15:09.120
set it to.

00:15:09.120 --> 00:15:11.880
And they are all text-based games.

00:15:11.880 --> 00:15:16.860
So they're fairly old school looking, like a lot of the games that people were programming

00:15:16.860 --> 00:15:19.480
in basic in the 1980s and 90s.

00:15:19.480 --> 00:15:26.140
But the plus side of that is that all of the games are really simple and you don't have to

00:15:26.140 --> 00:15:29.620
install additional libraries or modules or things like that.

00:15:29.620 --> 00:15:36.940
You can pretty much just type the code in and it just uses the Python standard library

00:15:36.940 --> 00:15:38.120
for all of this.

00:15:38.120 --> 00:15:41.540
I have a few of these programs that use a few other modules as well.

00:15:41.540 --> 00:15:46.420
But for the most part, you can get pretty far with just text and just ASCII art.

00:15:46.420 --> 00:15:52.640
And also, even if you already know Python, these programs are great just for ideas of if you

00:15:52.640 --> 00:15:55.860
want to learn another programming language and just get used to how things work in that.

00:15:56.200 --> 00:16:04.680
You could find the idea for a blackjack game from this collection of programs or this birthday paradox

00:16:04.680 --> 00:16:08.580
calculator and all sorts of these little projects right here.

00:16:08.580 --> 00:16:16.260
And of course, this book is also freely available online at inventwithpython.com slash bigbookpython.

00:16:16.260 --> 00:16:20.680
I'm starting to get reviews coming in on Amazon and they seem to be pretty positive.

00:16:20.680 --> 00:16:27.700
So I'm really hopeful about people just being able to take the next step in learning to code with this book.

00:16:28.000 --> 00:16:28.080
Yeah.

00:16:28.080 --> 00:16:28.340
Cool.

00:16:28.340 --> 00:16:28.900
Cool.

00:16:28.900 --> 00:16:29.380
Yeah.

00:16:29.380 --> 00:16:36.360
And then the other book that I had that came out in November is Beyond the Basic Stuff with Python,

00:16:36.360 --> 00:16:40.440
which is sort of the follow-up book to automate the boring stuff with Python.

00:16:40.760 --> 00:16:43.880
I had a lot of people who were asking me like, oh, I really like to automate.

00:16:43.880 --> 00:16:45.740
What should I read next?

00:16:45.740 --> 00:16:52.200
And I had like some things that I would tell them like fluent Python is a really great book,

00:16:52.200 --> 00:16:56.660
but it's also like 800 pages or 800 pounds or something.

00:16:56.660 --> 00:17:02.200
It's a really huge book and the information in it is great, but it's really intimidating to

00:17:02.200 --> 00:17:05.080
take this book and it's like, okay, read this one next.

00:17:05.940 --> 00:17:13.580
So I wanted to cover a book that had sort of the best practices for a lot of like software

00:17:13.580 --> 00:17:14.080
engineers.

00:17:14.080 --> 00:17:19.580
So there's sections on like how to name your variables or how to do code formatting.

00:17:19.580 --> 00:17:22.020
And then I talk about the black code formatting tool.

00:17:22.020 --> 00:17:25.260
I talk about type hints and how to write documentation.

00:17:25.260 --> 00:17:32.980
I have a very superficial coverage of Git and GitHub and how to use version control.

00:17:33.760 --> 00:17:38.220
And just, you know, and I even dive into like, what exactly does Pythonic mean?

00:17:38.220 --> 00:17:45.100
Spoiler alert, Pythonic basically means anything the person you're talking to wants it to mean

00:17:45.100 --> 00:17:45.680
at the time.

00:17:45.680 --> 00:17:50.640
But yeah, just sort of a lot of the things that you don't really get in your typical

00:17:50.640 --> 00:17:51.980
hello world tutorial.

00:17:51.980 --> 00:17:58.500
These are the sort of tidbits that you would pick up with experience over years of experience,

00:17:58.500 --> 00:17:58.900
I guess.

00:17:59.280 --> 00:18:03.540
but I just wanted to collect all of that advice and information and best practices into

00:18:03.540 --> 00:18:04.240
a single book.

00:18:04.240 --> 00:18:08.860
So yeah, that's also available online at the inventwithpython.com website.

00:18:08.860 --> 00:18:09.340
Cool.

00:18:09.340 --> 00:18:11.040
A couple of comments from the live stream.

00:18:11.040 --> 00:18:16.480
John Dehan says, beyond the basic stuff was great for learning to do things Python way.

00:18:16.480 --> 00:18:17.800
And wow.

00:18:17.800 --> 00:18:19.120
Great to see you, Mr. Swigert.

00:18:19.120 --> 00:18:23.300
Seems like only yesterday I was promoting your last book at Bay Piggies from...

00:18:23.300 --> 00:18:24.040
Oh, hey, Neil.

00:18:24.040 --> 00:18:24.720
How's it going?

00:18:24.720 --> 00:18:25.680
Cool.

00:18:26.020 --> 00:18:26.420
Yeah.

00:18:26.420 --> 00:18:26.620
Yeah.

00:18:26.620 --> 00:18:27.100
Very cool.

00:18:27.100 --> 00:18:28.620
Congrats on the books.

00:18:28.620 --> 00:18:30.760
Brian, let's go.

00:18:30.760 --> 00:18:32.740
Let's talk about something completely different than books.

00:18:32.740 --> 00:18:35.260
Like notebooks.

00:18:35.260 --> 00:18:36.720
Yes.

00:18:36.720 --> 00:18:38.720
Let's talk about notebooks.

00:18:38.720 --> 00:18:39.800
Thanks for popping that up.

00:18:39.800 --> 00:18:40.880
Yeah.

00:18:40.880 --> 00:18:43.420
So this was another suggestion.

00:18:43.420 --> 00:18:45.680
This suggestion came from David Nicholson.

00:18:45.680 --> 00:18:46.460
Thanks, David.

00:18:47.020 --> 00:18:51.660
I thought we'd covered this already, but then I looked in, but we haven't.

00:18:51.660 --> 00:18:56.420
And I looked into it and it's, and I obviously haven't played with it yet, but okay.

00:18:56.420 --> 00:18:58.600
So test book is very cool.

00:18:58.600 --> 00:18:59.220
Test book.

00:18:59.220 --> 00:19:02.060
The idea is to test your Jupyter notebooks.

00:19:02.060 --> 00:19:07.440
I think we've covered a couple things, ways to do that, but this is kind of a neat perspective.

00:19:07.440 --> 00:19:16.000
So the perspective of this is you've got a notebook with maybe, let's say, functions in it, and you want to check those.

00:19:16.000 --> 00:19:19.040
You want to make sure that you want to write tests against those functions.

00:19:19.260 --> 00:19:28.540
Instead of putting the tests in your notebook, put them in like just a test file and run it with pytest or UnitTest or something.

00:19:28.540 --> 00:19:38.060
And so to do that, though, like let's say I want to run a function foo and I want to do it from another file.

00:19:38.060 --> 00:19:41.020
I've got to get that definition of foo into my test code.

00:19:41.020 --> 00:19:55.000
And so what test book does is it has a decorator that you can either put it on your test or a fixture that goes ahead and runs the, one of the things you can do is run your notebook before the test runs.

00:19:55.000 --> 00:19:57.140
And then you can pull out the definitions.

00:19:57.140 --> 00:19:57.180
Oh yeah, this is really cool.

00:19:57.180 --> 00:20:02.900
So you have a decorator, which has a path to the IPYNB file and execute equals true.

00:20:03.020 --> 00:20:13.620
And by the time it gets to your code, it's already going to run that, that things defined like a function or variables defined within the notebook will just be accessible through the input parameter there.

00:20:13.620 --> 00:20:14.080
Yep.

00:20:14.080 --> 00:20:16.340
And the test gets a fix.

00:20:16.340 --> 00:20:20.760
You can have a fixture to be able to grab values, references.

00:20:20.760 --> 00:20:31.600
So the example we're showing right now shows pulling a function in, but I imagine you can pull in really anything, any name that exists within the notebook to be able to test it.

00:20:32.780 --> 00:20:39.200
some of the neat things that it includes right off the bat is it's nice that it doesn't, it isn't just by test.

00:20:39.200 --> 00:20:42.900
You can use it with unit test, apparently also with nose, but don't do that.

00:20:42.900 --> 00:20:53.780
one of the ways things you can do also is in the original example of decorating a test, it's going to run that notebook for every, every test it's decorated.

00:20:53.780 --> 00:20:55.500
You might not want that.

00:20:55.500 --> 00:20:56.180
You might.

00:20:56.180 --> 00:21:01.980
but if you want to run it all just once, you can put it in a fixture and then return the fixture.

00:21:01.980 --> 00:21:03.040
That's a cool thing.

00:21:03.040 --> 00:21:12.260
one reason why you might want to run it multiple times is if, if there are interactions between the different parts and you want to completely isolate those tests.

00:21:12.260 --> 00:21:14.640
Another thing that's built into it is patching.

00:21:14.640 --> 00:21:16.560
So you don't have to import mock.

00:21:16.560 --> 00:21:24.820
You can patch different parts of your, your Python code, your Python notebook, your notebook code, with, like, like mock.

00:21:25.040 --> 00:21:27.340
you can patch it right through this.

00:21:27.340 --> 00:21:28.360
So that's pretty neat.

00:21:28.360 --> 00:21:29.300
Yeah, that's pretty neat.

00:21:29.300 --> 00:21:30.120
I like it.

00:21:30.120 --> 00:21:30.880
Al, what do you think?

00:21:30.880 --> 00:21:31.540
Nice.

00:21:31.540 --> 00:21:31.940
Yeah.

00:21:31.940 --> 00:21:41.800
I haven't had a lot of experience with Jupyter notebooks, but it's, it's sort of becoming the main way that a lot of people are being introduced to Python, especially if they're coming from, the sciences or academia.

00:21:42.100 --> 00:21:42.440
Yep.

00:21:42.560 --> 00:21:42.800
Yeah.

00:21:42.800 --> 00:21:51.280
And so getting like sort of a lot of, informally trained software engineers, up to speed with, with like unit testing and other practices like that.

00:21:51.280 --> 00:21:53.180
It's definitely something I can get behind.

00:21:53.180 --> 00:21:53.960
Yeah, that's cool.

00:21:54.000 --> 00:22:00.800
And the, getting the ability to call those pieces or interact with those pieces outside the notebook is quite tricky.

00:22:00.800 --> 00:22:02.780
So this is a neat way to do it.

00:22:02.780 --> 00:22:06.920
I mean, we've got paper mail, but I'm not sure exactly how that folds into testing and stuff like that.

00:22:06.920 --> 00:22:07.120
Right.

00:22:07.120 --> 00:22:07.760
Right.

00:22:07.760 --> 00:22:08.180
Actually.

00:22:08.180 --> 00:22:08.740
Yeah.

00:22:08.740 --> 00:22:09.200
Yeah.

00:22:09.200 --> 00:22:09.820
I don't think so.

00:22:09.820 --> 00:22:13.380
I think it's more like inputs and outputs as a whole notebook.

00:22:13.380 --> 00:22:17.820
Not like, let me get ahold of the function in the cell seven and try to call that.

00:22:17.820 --> 00:22:19.100
Yeah.

00:22:19.100 --> 00:22:21.560
Also, the target audience is different.

00:22:21.560 --> 00:22:27.720
So the target audience for your notebook itself is different than you trying to test your code.

00:22:27.720 --> 00:22:34.500
So, keeping the test code out of the notebook, I think is a nice thing to, to keep it clean.

00:22:34.500 --> 00:22:35.820
Yeah, I totally agree.

00:22:35.820 --> 00:22:37.720
taking a step back real quick.

00:22:37.720 --> 00:22:43.720
Neil also asks, are the small programs in your book, Al, compatible with MicroPython or CircuitPython?

00:22:43.720 --> 00:22:45.780
Probably not.

00:22:45.780 --> 00:22:47.940
I don't know.

00:22:47.940 --> 00:22:50.740
I haven't taken too much of a look at MicroPython.

00:22:51.140 --> 00:22:58.200
but I do try to keep, all the source code as simple as possible and not really rely

00:22:58.200 --> 00:23:00.840
on like the file system or making network connections.

00:23:00.840 --> 00:23:06.520
Mostly it's just standard IO, input output streams for, for text.

00:23:06.520 --> 00:23:12.300
So, you know, if, if it can run print and input, then likely it can, run these programs.

00:23:12.300 --> 00:23:12.820
Yeah.

00:23:12.820 --> 00:23:16.000
Maybe you just have to make the little lights blink and some sort of Morse code.

00:23:16.000 --> 00:23:16.600
Yeah.

00:23:16.600 --> 00:23:17.140
Perfect.

00:23:17.140 --> 00:23:18.560
Nice.

00:23:18.880 --> 00:23:19.220
All right.

00:23:19.220 --> 00:23:24.520
Something that is a little bit mysterious to a lot of folks, I think partly because it's

00:23:24.520 --> 00:23:30.160
somewhat discouraged, but not always is from package import star, right?

00:23:30.160 --> 00:23:33.820
Well, sometimes discouraged because you probably shouldn't.

00:23:33.820 --> 00:23:36.400
There probably are situations where you want to do that.

00:23:36.500 --> 00:23:40.480
Like if I've got three sub modules and I want to take the elements in them and then like

00:23:40.480 --> 00:23:45.940
drop them into the top level __init__() for a package so that I can just say package name

00:23:45.940 --> 00:23:48.800
dot items, but not organize them into one giant file.

00:23:48.800 --> 00:23:50.500
For example, that might be reasonable.

00:23:50.620 --> 00:23:58.320
The way that you control that is you work on the dunder all definition at the top of your package,

00:23:58.320 --> 00:23:58.540
right?

00:23:58.540 --> 00:24:02.600
And in there you can say, oh, here are the names of the things that I would like to export.

00:24:02.600 --> 00:24:06.980
If you import star rather than everything, give them these, right?

00:24:06.980 --> 00:24:13.040
Maybe you define some weird thing called Django and it's not meant to override Django or something

00:24:13.040 --> 00:24:13.680
like that, right?

00:24:13.680 --> 00:24:15.040
You want to leave that out.

00:24:15.340 --> 00:24:17.340
So how do you manage that?

00:24:17.340 --> 00:24:23.440
Well, there's this project over on GitHub called auto all, auto dash all.

00:24:23.440 --> 00:24:29.660
And the idea is it somewhat automagically manages the dunder all variable for Python modules.

00:24:29.660 --> 00:24:32.480
So there's a couple of ways in which you can do it.

00:24:32.480 --> 00:24:36.080
You can exclude certain things.

00:24:36.080 --> 00:24:41.060
You can clearly differentiate what's meant to be treated as an external item and what's meant

00:24:41.060 --> 00:24:42.660
to be treated as an internal item.

00:24:43.100 --> 00:24:48.020
You don't have to worry about continuing to update the dunder all and so on.

00:24:48.020 --> 00:24:49.840
So you just pip install it.

00:24:49.840 --> 00:24:56.940
And then the most, it seems like the recommended way, I guess, is you would fall somewhere in

00:24:56.940 --> 00:25:00.300
your script at the top level, like at the function or class level, right?

00:25:00.300 --> 00:25:03.260
No tab space, no spaces, no indentation.

00:25:03.260 --> 00:25:07.360
You say start all, then you write a bunch of code functions and so on.

00:25:07.360 --> 00:25:08.080
And then you say-

00:25:08.080 --> 00:25:09.500
You mean auto all dot start all?

00:25:10.420 --> 00:25:10.820
Yeah, yeah, yeah.

00:25:10.820 --> 00:25:13.540
If you, if you, yeah, if you, exactly.

00:25:13.540 --> 00:25:14.820
If you import it from there, right?

00:25:14.820 --> 00:25:16.360
I guess you could even import star from there.

00:25:16.360 --> 00:25:19.900
But you say start all, and then you write a bunch of code and then you say end all.

00:25:19.900 --> 00:25:25.160
And then basically between those two markers, those are the things that go into your dunder all

00:25:25.160 --> 00:25:25.640
variable.

00:25:25.640 --> 00:25:27.680
There's something about classes.

00:25:27.680 --> 00:25:31.080
It will not work for classes or variables as well.

00:25:31.080 --> 00:25:32.040
Sorry, take it back.

00:25:32.280 --> 00:25:34.080
It will with the start all, end all.

00:25:34.080 --> 00:25:37.660
But there's also another way that only works on various functions.

00:25:37.660 --> 00:25:42.880
And that is to put a decorator onto the function, which I think, I like this a lot, but the fact

00:25:42.880 --> 00:25:47.240
that it doesn't work with classes, it sounds like that should actually be a PR folks, a little

00:25:47.240 --> 00:25:51.120
thing that, an extra one, like public class or I don't know, whatever.

00:25:51.120 --> 00:25:51.980
But that seems pretty cool.

00:25:51.980 --> 00:25:56.680
So you just say at public on a function, and then that will add it to the dunder all.

00:25:57.020 --> 00:26:00.280
So if you want to export three functions from your module, you just put at public on those.

00:26:00.280 --> 00:26:02.440
And that way, when you're looking at it, it's like really clear.

00:26:02.440 --> 00:26:04.540
These are the public functions and the rest aren't.

00:26:04.540 --> 00:26:09.980
I mean, you could still from module import name, but not through the all, right?

00:26:09.980 --> 00:26:10.480
Yeah.

00:26:10.480 --> 00:26:10.980
Okay.

00:26:10.980 --> 00:26:12.440
Anyway, it looks pretty cool, right?

00:26:12.440 --> 00:26:18.380
Yeah, that is actually a really nice way to just have this automatically taken care of.

00:26:18.380 --> 00:26:24.700
I mean, ideally, you're not really doing the from module import star all too often, or

00:26:24.700 --> 00:26:29.100
rather, ideally, I'm the only person in the entire world that should be allowed to do that.

00:26:29.100 --> 00:26:32.140
And everybody else will have to do it the proper way.

00:26:32.140 --> 00:26:32.880
It's a bad idea.

00:26:32.880 --> 00:26:33.440
Don't do it.

00:26:33.440 --> 00:26:34.360
But it's very handy.

00:26:34.360 --> 00:26:34.680
No.

00:26:34.680 --> 00:26:36.080
Yeah, this is really handy.

00:26:36.080 --> 00:26:36.720
Yeah.

00:26:36.720 --> 00:26:39.680
Dean out there in the live stream says this should work with a context manager.

00:26:39.680 --> 00:26:40.940
Yeah, it probably should.

00:26:40.940 --> 00:26:45.440
I think the challenge would be then you'd have like all of your implementation indented, but

00:26:45.440 --> 00:26:46.300
still pretty cool.

00:26:46.300 --> 00:26:47.000
Yeah.

00:26:47.000 --> 00:26:56.120
So actually, I'm reminded of one of the places I do do import all or import star is in dunder

00:26:56.120 --> 00:26:57.540
init files for packages.

00:26:57.540 --> 00:26:58.540
Yes, exactly.

00:26:58.540 --> 00:27:01.320
In those cases, I often do pull in.

00:27:01.320 --> 00:27:05.560
I've got a couple modules that have my interface and I pull everything in from there.

00:27:06.560 --> 00:27:11.340
So those are cases where that is something that happens.

00:27:11.340 --> 00:27:15.540
And then you're faced with, well, what if I want to put another function that isn't part

00:27:15.540 --> 00:27:16.420
of my public interface?

00:27:16.420 --> 00:27:17.440
Then you have to jump through hoops.

00:27:17.440 --> 00:27:19.720
So I'd probably use it in those cases.

00:27:19.720 --> 00:27:20.720
Yeah.

00:27:20.720 --> 00:27:24.100
I don't think it's broadly applicable, but for the people who are really trying to carefully

00:27:24.100 --> 00:27:26.800
manage their dunder all, it seems nice.

00:27:26.800 --> 00:27:27.480
Straightforward.

00:27:27.480 --> 00:27:27.760
Simple.

00:27:27.760 --> 00:27:28.320
Yeah.

00:27:28.320 --> 00:27:28.780
Yeah.

00:27:28.780 --> 00:27:29.260
Yep.

00:27:29.260 --> 00:27:29.940
All right.

00:27:29.940 --> 00:27:32.860
Al, I think you got the last one, right?

00:27:32.860 --> 00:27:33.500
Yeah.

00:27:33.500 --> 00:27:36.380
So I am working on another book.

00:27:36.380 --> 00:27:39.540
I have a really bad book writing problem.

00:27:39.540 --> 00:27:45.060
I keep thinking that this will be the last one and then I have ideas for 10 or 20 more.

00:27:45.060 --> 00:27:50.720
But the book that I'm currently working on and I'm down to the drafts of the last two chapters

00:27:50.720 --> 00:27:52.120
is a book on recursion.

00:27:52.120 --> 00:27:55.100
So this is currently my untitled recursion book.

00:27:55.760 --> 00:28:03.500
But yeah, I gave a talk at North Bay Python, I believe in 2018 or 2019, that was an introduction

00:28:03.500 --> 00:28:04.320
to recursion.

00:28:04.320 --> 00:28:10.640
And recursion is one of those things where a lot of people find it very intimidating or

00:28:10.640 --> 00:28:12.180
even just outright magical.

00:28:12.180 --> 00:28:17.740
And it's this thing that seems to be like only for advanced programmers or something like

00:28:17.740 --> 00:28:18.020
that.

00:28:18.020 --> 00:28:20.600
But I started taking a look at it.

00:28:20.600 --> 00:28:21.980
Or beginner programmers who make a mistake.

00:28:21.980 --> 00:28:22.900
Oh, yeah.

00:28:22.900 --> 00:28:23.520
Right.

00:28:23.520 --> 00:28:24.020
Exactly.

00:28:24.020 --> 00:28:24.700
Accidentally.

00:28:24.700 --> 00:28:25.620
Just keep calling it.

00:28:25.620 --> 00:28:26.060
Yeah.

00:28:26.060 --> 00:28:27.580
Just for some general background.

00:28:27.580 --> 00:28:31.700
Recursion is when you have a function that calls itself.

00:28:31.700 --> 00:28:35.320
And this is it sounds like it won't work.

00:28:35.320 --> 00:28:36.580
And oftentimes it won't.

00:28:36.580 --> 00:28:41.640
You'll get a sort of an infinite loop of recursive function calls and then it crashes your program.

00:28:41.640 --> 00:28:48.100
But there are recursive algorithms where this is a really handy technique and allows you to

00:28:48.100 --> 00:28:50.980
do really sophisticated things in not that much code.

00:28:50.980 --> 00:28:53.600
However, a lot of people find it really confusing.

00:28:53.800 --> 00:28:57.200
But more than anything, I found that it's just poorly taught.

00:28:57.200 --> 00:29:02.840
Most people will probably learn this from a computer science professor or they'll be studying

00:29:02.840 --> 00:29:06.580
it as a way to prepare for job interviews for the coding section.

00:29:07.240 --> 00:29:11.180
You know, there's a lot of times where people will be writing out an algorithm on a whiteboard

00:29:11.180 --> 00:29:15.380
and their interviewer will say like, OK, and now can you do the recursive version of this

00:29:15.380 --> 00:29:17.940
algorithm as a quick gotcha?

00:29:18.580 --> 00:29:26.080
But yeah, there's the short of it is I realized that a lot of times people don't really teach the concept of the call stack.

00:29:26.080 --> 00:29:35.280
And without explicitly knowing about what a call stack is and how it works, a lot of what recursion does kind of just seems magical because you're missing this huge piece.

00:29:35.280 --> 00:29:37.780
And I found out so many other things about this.

00:29:37.840 --> 00:29:44.720
And so I thought, hey, I could write a quick little tutorial on recursive functions and make a talk.

00:29:44.720 --> 00:29:47.540
And then that just kind of ballooned into a giant book now.

00:29:48.680 --> 00:29:49.880
That's how I end up with courses.

00:29:49.880 --> 00:29:52.080
I'm like, oh, that'd be a neat little thing to play around with.

00:29:52.080 --> 00:29:54.120
Why have I spent the last month doing this?

00:29:54.120 --> 00:29:55.220
Yes.

00:29:55.220 --> 00:30:03.440
So I'm hoping to have this book probably done either at the end of this year or early next year in 2022.

00:30:03.440 --> 00:30:13.900
But yeah, so a book that just covers recursive algorithms and and why people find recursion to be so intimidating and how it really isn't.

00:30:13.900 --> 00:30:19.100
And even how oftentimes it's actually not the best technique to use.

00:30:19.100 --> 00:30:22.000
You just want to write straightforward, simple code.

00:30:22.000 --> 00:30:29.620
But if you really want to show off how smart you are and annoy your coworkers that way, recursion is also really great for that.

00:30:29.620 --> 00:30:34.880
What I like about it is if you have hierarchical data, it matches that really cleanly.

00:30:34.880 --> 00:30:35.360
Yes.

00:30:35.360 --> 00:30:38.020
You want to traverse a tree, but in like a real simple way.

00:30:38.020 --> 00:30:45.700
Or you want to work with an algorithm that is like iterative in the sense like the previous step kind of naturally the answer that leads to the next one.

00:30:45.700 --> 00:30:46.680
Those types of things.

00:30:46.680 --> 00:30:48.700
It's like a super elegant answer.

00:30:48.700 --> 00:30:49.360
Yeah.

00:30:49.360 --> 00:30:57.860
I found that recursive algorithms are really great when your problem has a tree like structure and also involves backtracking.

00:30:58.460 --> 00:31:04.580
Otherwise, there's probably you probably just need a loop or some iterative way of solving it.

00:31:04.580 --> 00:31:08.820
You can also come up with a cool joke like the one we had on episode 236.

00:31:08.820 --> 00:31:12.080
There are so many recursive jokes.

00:31:12.080 --> 00:31:18.340
I actually opened up my talk at North Bay Python with just like, OK, we just got to get that out of our systems.

00:31:18.340 --> 00:31:23.520
Do the whole, you know, in order to learn about recursion, you first have to learn about recursion.

00:31:23.720 --> 00:31:26.360
These jokes that we've heard like millions of times.

00:31:26.360 --> 00:31:27.220
Yeah.

00:31:27.220 --> 00:31:31.860
People can check out the little cartoon graphic thing on episode 236.

00:31:31.860 --> 00:31:32.320
Yeah.

00:31:32.320 --> 00:31:33.620
I was going to ask you if you're right.

00:31:33.620 --> 00:31:35.800
You got anything you want to just throw out there at the end?

00:31:35.800 --> 00:31:39.160
No, I've just been working a lot.

00:31:39.160 --> 00:31:41.100
I was just one question.

00:31:41.100 --> 00:31:45.680
I was just going to think that maybe Al's book was about how to write a book about recursion.

00:31:45.680 --> 00:31:49.720
The making of is something that I've also been thinking of.

00:31:49.720 --> 00:31:54.900
I feel like a book on meta classes and meta programming might be very relevant.

00:31:54.900 --> 00:31:56.900
All right.

00:31:56.900 --> 00:31:58.760
I got a couple of things to cover for my extras.

00:31:58.760 --> 00:31:59.240
OK.

00:31:59.240 --> 00:32:01.940
First, I had talked about Oh My Posh.

00:32:01.940 --> 00:32:07.580
Oh My Posh, which I think is a really cool like Oh My Z shell type of thing.

00:32:07.680 --> 00:32:20.440
But for PowerShell and if you use the new Windows terminal and you get the new PowerShell 7 and set that to be the default, then you get these really beautiful, nice prompts and autocomplete and all those kinds of things.

00:32:20.440 --> 00:32:21.780
So those are really neat.

00:32:21.780 --> 00:32:25.240
People can check that out for all the Posh shell stuff.

00:32:25.800 --> 00:32:30.260
But someone was asking for something that would do a thing that is really cool.

00:32:30.260 --> 00:32:36.020
Like what if what if when I and oh, by the way, because we gave it a shout out, right?

00:32:36.020 --> 00:32:48.080
I was dreaming of something that would automatically activate virtual environments when I seeded into a structure that contained in the tree somewhere a virtual environment, which is cool.

00:32:48.460 --> 00:32:54.740
So they dug around and said, I found this thing called Posh dash Dure Envy, which does that.

00:32:54.740 --> 00:33:01.440
So as you change into the directory, it will automatically activate virtual environments.

00:33:01.440 --> 00:33:02.040
Nice.

00:33:02.040 --> 00:33:02.720
Nice.

00:33:02.720 --> 00:33:03.600
Yeah.

00:33:03.600 --> 00:33:04.920
So that's pretty neat.

00:33:04.920 --> 00:33:06.220
So people can check that out.

00:33:06.220 --> 00:33:07.340
It's a sort of follow up.

00:33:07.340 --> 00:33:08.020
Another thing.

00:33:08.020 --> 00:33:13.440
One of our listeners, Einstein, Vincent, I believe is the one who sent it over.

00:33:13.440 --> 00:33:14.040
Thank you for that.

00:33:14.040 --> 00:33:15.480
Just said, hey, quick shout out.

00:33:15.480 --> 00:33:17.540
Your show has been super helpful to us.

00:33:17.600 --> 00:33:19.820
It's been inspiring a bunch of us scientists.

00:33:19.820 --> 00:33:23.940
We're here in Iceland and I believe also at Harvard, if I recall correctly.

00:33:23.940 --> 00:33:38.320
And they now publish an article using Python, a scalable method of determining physiological endotypes for basically a sleep apnea study of trying to turn this into more of a continuum rather than yes or no.

00:33:38.320 --> 00:33:39.420
You have yes or no.

00:33:39.420 --> 00:33:41.620
You yes do or don't have sleep apnea.

00:33:41.620 --> 00:33:46.680
So really cool just to see listeners listening to the show, using some of the packages and doing cool stuff that help people.

00:33:46.740 --> 00:33:47.220
Yes.

00:33:47.220 --> 00:33:51.000
one more follow up to three more follow ups, actually.

00:33:51.000 --> 00:33:52.620
But next one really quickly.

00:33:52.620 --> 00:34:00.580
I've been having such a challenge with email for two years and I have finally, I think solved it.

00:34:00.580 --> 00:34:01.380
The beast.

00:34:01.600 --> 00:34:07.120
I believe I have had hundreds of emails from years ago that needed action.

00:34:07.120 --> 00:34:12.600
And finally, I've gotten back to almost everybody down to just a handful of emails and I'll have them all done.

00:34:12.600 --> 00:34:14.500
But anyway, I want to recommend two email clients.

00:34:14.500 --> 00:34:15.680
One for the Mac is Newton.

00:34:15.680 --> 00:34:16.400
Pretty cool.

00:34:16.500 --> 00:34:20.820
And then I'm going to give superhuman a try, but it takes a while to get set up on that.

00:34:21.460 --> 00:34:23.480
If you're out there struggling with email, check those out.

00:34:23.480 --> 00:34:26.400
And so we've heard about cloud computing.

00:34:26.400 --> 00:34:28.380
That's where you might run your program in the cloud.

00:34:28.380 --> 00:34:31.520
You've heard about virtual environment or sorry, virtual machines.

00:34:31.520 --> 00:34:36.440
That's where you might fire up a computer that runs in a container or a virtual hypervisor.

00:34:36.600 --> 00:34:39.400
And then you can interact with that in like its own little way.

00:34:39.400 --> 00:34:42.660
But Microsoft, apparently I was just reading like 15 minutes before we started.

00:34:42.660 --> 00:34:43.560
I thought I'd throw this in there.

00:34:43.560 --> 00:34:52.320
They just reveal not just Windows 11, but Windows 365, which is basically you buy Windows and the thing hosted in the cloud.

00:34:52.320 --> 00:34:54.600
So you just like in a web browser to it or something.

00:34:54.600 --> 00:34:57.580
And then you have a computer with all your files that's instantly on.

00:34:57.580 --> 00:34:58.360
So I don't know.

00:34:58.360 --> 00:34:59.380
I thought that was kind of interesting.

00:34:59.380 --> 00:35:00.080
Throw that out there.

00:35:00.080 --> 00:35:03.680
It's like Office 365, except the entire operating system.

00:35:03.680 --> 00:35:06.360
The entire computer with all your files like saved there.

00:35:06.440 --> 00:35:06.860
Yeah, exactly.

00:35:06.860 --> 00:35:07.860
Probably expensive.

00:35:07.860 --> 00:35:08.440
I have no idea.

00:35:08.440 --> 00:35:09.560
Last thing.

00:35:09.560 --> 00:35:12.620
We talked about Flock No, right?

00:35:12.620 --> 00:35:18.260
We talked about Flock and the vanishing of third-party cookies and the stuff that Google is trying to do.

00:35:18.260 --> 00:35:21.300
And then remember that Brian, you pointed out they received significant feedback.

00:35:21.300 --> 00:35:23.620
That was not totally positive for them.

00:35:23.620 --> 00:35:24.060
Yeah.

00:35:24.060 --> 00:35:33.060
So, you know, parallel to that, I think, is really interesting is that Apple also had their do not track thing that they put on their phone, which is fine.

00:35:33.060 --> 00:35:35.360
But I think it just needs to be way more than that.

00:35:35.400 --> 00:35:36.320
But yeah, so they have that.

00:35:36.320 --> 00:35:40.560
And would you be surprised that only 25% of the people said, yes, please track me?

00:35:40.560 --> 00:35:43.920
I'm actually surprised that 25% of the people said yes.

00:35:43.920 --> 00:35:47.360
Like, if it's over 5%, it's blowing my mind, right?

00:35:47.360 --> 00:35:47.700
Like, yeah.

00:35:47.700 --> 00:35:49.560
Who's saying yes?

00:35:50.860 --> 00:35:51.380
Exactly.

00:35:51.380 --> 00:35:52.620
So here's an article.

00:35:52.620 --> 00:35:58.180
Facebook and its advertisers are panicking as the majority of iPhone users opt out of tracking.

00:35:58.180 --> 00:36:05.760
And I saw that 20% of ad spend has now moved away from iPhone and towards Android because Android doesn't, you know, they're happy to track you.

00:36:05.760 --> 00:36:06.340
That's Google.

00:36:06.340 --> 00:36:06.760
Yeah.

00:36:07.240 --> 00:36:09.880
But also just I think it's very meta and funny.

00:36:09.880 --> 00:36:16.880
So I have my VPN that has a ad blocker plus cyber, like basically virus malware detector at the network layer.

00:36:16.880 --> 00:36:19.860
Notice there's a big gap in me showing you this article up here.

00:36:19.860 --> 00:36:24.640
That's as we're trying to show me the ad about the advertisers and my network.

00:36:24.880 --> 00:36:26.960
My VPN is blocking it, which I just love it.

00:36:26.960 --> 00:36:30.960
So anyway, those are all the things that I had to share there.

00:36:30.960 --> 00:36:32.900
Al, you got anything else you want to throw out there for everyone?

00:36:32.900 --> 00:36:33.620
Yeah.

00:36:33.620 --> 00:36:39.480
Outside of the books, I'm also working on my open source project called PyAutoGUI.

00:36:39.480 --> 00:36:46.280
This is a GUI automation module for Python where it's a module that lets your Python scripts control the mouse and keyboard.

00:36:46.280 --> 00:36:53.600
So if you have some software that you want to automatically click and type things into, you can write a script using PyAutoGUI to do that.

00:36:53.700 --> 00:36:58.220
It works on Python 2 and 3 and also on Windows, macOS and Linux.

00:36:58.220 --> 00:37:04.060
I feel like I've been neglecting this project for the longest time, but more and more people are using it.

00:37:04.060 --> 00:37:12.200
So I really want to start adding more and more features to bring it up to speed with a lot of other GUI automation libraries that are out there.

00:37:12.200 --> 00:37:16.780
So if anybody is interested in contributing, I have the GitHub link.

00:37:16.780 --> 00:37:22.520
And you can also just Google for PyAutoGUI to find more information about that.

00:37:22.860 --> 00:37:25.520
That's cool. I found out by Googling with DuckDuckGo.

00:37:25.520 --> 00:37:26.160
Yes.

00:37:26.160 --> 00:37:30.700
I still have a problem saying Google as the verb.

00:37:30.700 --> 00:37:32.120
No, I do too.

00:37:32.120 --> 00:37:38.620
I finally got over using guys as a general neutral pronoun, but now I still have problems saying Google all the time.

00:37:38.620 --> 00:37:38.860
Yeah.

00:37:38.860 --> 00:37:40.460
It's all hard.

00:37:40.460 --> 00:37:41.980
By the way, notice over here.

00:37:42.260 --> 00:37:45.520
I still have trouble not telling people to MapQuest something.

00:37:45.520 --> 00:37:46.680
Yeah, I know.

00:37:47.520 --> 00:37:52.540
It's good, except those little arrows to move each around on the map of little bars on each side.

00:37:52.540 --> 00:37:53.920
It's so clunky.

00:37:53.920 --> 00:37:57.140
And you got to print the thing out for like five pages and follow the pictures.

00:37:57.140 --> 00:38:02.280
No, but so one thing I do want to give a quick shout out to the guys that read the docs, Eric and crew over there.

00:38:02.820 --> 00:38:07.140
Like they have an ad right here and it says sponsored ads serve ethically.

00:38:07.140 --> 00:38:08.500
You know what that's based on?

00:38:08.500 --> 00:38:10.240
Not tracking and retargeting.

00:38:10.240 --> 00:38:13.520
That's just, hey, there's something to do with this Python project.

00:38:13.520 --> 00:38:16.960
So this ad has to do with the context of what is here.

00:38:16.960 --> 00:38:19.820
It's relevant to the content I'm already looking at.

00:38:19.820 --> 00:38:20.860
Good old fashioned.

00:38:20.860 --> 00:38:21.720
That's astounding.

00:38:22.380 --> 00:38:24.880
Just like magazines and newspapers and stuff like that.

00:38:24.880 --> 00:38:27.980
And it's not about finding hot singles in my local area.

00:38:27.980 --> 00:38:30.700
That's great.

00:38:30.700 --> 00:38:31.540
Exactly.

00:38:31.540 --> 00:38:32.820
All right.

00:38:32.820 --> 00:38:33.480
Cool.

00:38:33.480 --> 00:38:34.000
Yeah.

00:38:34.000 --> 00:38:34.440
Cool.

00:38:34.440 --> 00:38:34.880
Thanks.

00:38:34.880 --> 00:38:36.820
Thanks, Al, for joining us today.

00:38:36.820 --> 00:38:38.380
And Brian, as always.

00:38:38.380 --> 00:38:39.620
Thanks for having me.

00:38:39.620 --> 00:38:40.320
Yeah, you bet.

00:38:40.320 --> 00:38:41.420
Thanks, everyone, for listening.

00:38:41.420 --> 00:38:43.260
Thanks for listening to Python Bytes.

00:38:43.260 --> 00:38:46.060
Follow the show on Twitter via at Python Bytes.

00:38:46.060 --> 00:38:49.160
That's Python Bytes as in B-Y-T-E-S.

00:38:49.160 --> 00:38:51.980
Get the full show notes over at Pythonbytes.fm.

00:38:52.300 --> 00:38:56.860
If you have a news item we should cover, just visit Pythonbytes.fm and click submit in the

00:38:56.860 --> 00:38:57.280
nav bar.

00:38:57.280 --> 00:38:59.400
We're always on the lookout for sharing something cool.

00:38:59.400 --> 00:39:03.860
If you want to join us for the live recording, just visit the website and click live stream

00:39:03.860 --> 00:39:06.740
to get notified of when our next episode goes live.

00:39:06.740 --> 00:39:11.100
That's usually happening at noon Pacific on Wednesdays over at YouTube.

00:39:11.100 --> 00:39:14.460
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:39:14.460 --> 00:39:18.180
Thank you for listening and sharing this podcast with your friends and colleagues.

