WEBVTT

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

00:00:05.480 --> 00:00:09.680
This is episode 112, according to January 9th, 2019.

00:00:09.680 --> 00:00:10.620
I'm Michael Kennedy.

00:00:10.620 --> 00:00:11.480
And I'm Brian Okken.

00:00:11.480 --> 00:00:12.400
Hey, Brian. How are you doing?

00:00:12.400 --> 00:00:15.020
I am great. It's a wonderful January.

00:00:15.020 --> 00:00:19.120
We're starting to get back into the swing of things. The news is starting to flow again.

00:00:19.120 --> 00:00:19.640
Yes.

00:00:19.640 --> 00:00:26.000
Yeah, absolutely. Now, before we get into it, I just want to say thank you to Datadog for sponsoring the show,

00:00:26.000 --> 00:00:29.260
as they are many of our shows. So, tell you more about them later.

00:00:29.760 --> 00:00:37.560
Right now, I want to just think back to what it was like to have my programming and computer science assignments graded.

00:00:37.560 --> 00:00:45.040
They were like, here is an algorithm. Write the output with a pencil on a piece of paper.

00:00:45.040 --> 00:00:46.740
We've come a long way from there, right?

00:00:46.740 --> 00:00:53.560
Yeah. I mean, I even remember, I guess, turning in floppy disks and code printouts and stuff like that.

00:00:53.560 --> 00:00:54.760
Because what are you going to do? Go for them?

00:00:54.760 --> 00:00:59.000
First thing I want to talk about is a thing called NB Grader.

00:00:59.520 --> 00:01:01.120
That's short for Notebook Grader.

00:01:01.120 --> 00:01:05.400
And this, I just ran across this. This is just so totally cool.

00:01:05.400 --> 00:01:07.840
I'm just going to read there, the little thing.

00:01:07.840 --> 00:01:11.940
There was an article about it in Journal of Open Source Education.

00:01:11.940 --> 00:01:13.600
Beginning of the summary is,

00:01:13.600 --> 00:01:18.340
NB Grader is a flexible tool for creating and grading assignments in the Jupyter Notebook.

00:01:18.340 --> 00:01:23.280
NB Grader allows instructors to create a single master copy of an assignment,

00:01:23.400 --> 00:01:25.740
including tests and canonical solutions.

00:01:25.740 --> 00:01:31.320
From the master copy, a student version is generated without the solutions, thus obviating.

00:01:31.320 --> 00:01:33.720
That's totally a smarty word.

00:01:33.720 --> 00:01:37.100
Anyway, thus obviating the need to maintain two separate versions.

00:01:37.500 --> 00:01:44.860
NB Grader also automatically grades submitted assignments by executing the notebooks and storing the results of the test in a database.

00:01:44.860 --> 00:01:53.480
After auto grading, instructors can manually grade free responses and provide partial credit using the Form Grader Jupyter Notebook extension.

00:01:54.480 --> 00:01:59.300
Finally, instructors can use NB Grader to leave personalized feedback for each student submission,

00:01:59.300 --> 00:02:02.620
including comments as well as detailed error information.

00:02:02.620 --> 00:02:03.620
That sounds super useful.

00:02:03.620 --> 00:02:05.820
I totally want to play with that, even though I'm not a teacher.

00:02:06.320 --> 00:02:12.040
We're also linking to the NB Grader documentation that has a little intro video on how it all works.

00:02:12.040 --> 00:02:14.600
And wow, it just looks totally cool.

00:02:14.600 --> 00:02:18.220
That seems like an awesome way to grade computer science stuff.

00:02:18.220 --> 00:02:24.400
And you could grade pretty much anything that is reasonable to compute within a Jupyter Notebook, right?

00:02:24.740 --> 00:02:30.940
So I guess the people would have to have some Python or some sort of skill where they interact with it.

00:02:30.940 --> 00:02:39.160
But maybe that could be really simple, like just put an answer or a number or something into a cell that then gets stored and checked.

00:02:39.160 --> 00:02:48.620
But the thing that was kind of a concern for me as you're describing it was, well, what if there's like a super simple mistake you make?

00:02:48.620 --> 00:02:52.140
And then the answer is way off, so you just get it wrong, right?

00:02:52.140 --> 00:02:57.100
But the fact that you can go back and give partial credit and like evaluate it, that sounds pretty cool.

00:02:57.100 --> 00:03:03.180
Like a lot of the stuff, if you've got tests in place where it just checks their code and all the people that got it right,

00:03:03.180 --> 00:03:05.920
you don't have to really go back and double check that stuff.

00:03:05.920 --> 00:03:10.180
Maybe spot check to make sure they're not all right in the same answer or something.

00:03:10.180 --> 00:03:11.940
But it looks like a lot of fun.

00:03:11.940 --> 00:03:12.500
Yeah, that's cool.

00:03:12.500 --> 00:03:15.860
I was a TA in college and had to grade a lot of like calculus tests and stuff.

00:03:15.860 --> 00:03:20.780
This seems really lovely compared to the alternative, honestly.

00:03:20.780 --> 00:03:21.340
It's great.

00:03:21.340 --> 00:03:21.580
Yeah.

00:03:21.720 --> 00:03:24.900
Sometimes when people are doing their assignments, they can get pretty upset.

00:03:24.900 --> 00:03:26.120
Things aren't working out.

00:03:26.120 --> 00:03:27.120
It's really frustrating.

00:03:27.120 --> 00:03:27.640
Yeah.

00:03:27.640 --> 00:03:28.540
They might even swear.

00:03:28.540 --> 00:03:29.220
They might.

00:03:29.220 --> 00:03:37.680
And they might do it in like a public forum or maybe they do it in like a GitHub commit that is going to be public and you don't want it there.

00:03:37.680 --> 00:03:39.760
So you might want to check that.

00:03:39.760 --> 00:03:47.040
And there's a couple of ways to check for profanity check.

00:03:47.040 --> 00:03:48.080
Profanity check.

00:03:48.080 --> 00:03:49.280
Profanity dash check.

00:03:49.920 --> 00:03:50.920
So what's cool about this.

00:03:50.920 --> 00:03:51.740
So what's cool about this.

00:03:51.740 --> 00:04:00.340
I mean, obviously you could say, does it have these seven words or whatever, but this one takes AI and applies it to this problem.

00:04:00.340 --> 00:04:01.000
Basically.

00:04:01.000 --> 00:04:01.800
Wow.

00:04:01.880 --> 00:04:10.840
It takes a linear SVM model trained on 200,000 human labeled samples of clean and profane text.

00:04:10.840 --> 00:04:13.360
So this string is bad.

00:04:13.360 --> 00:04:15.300
This sentence is good.

00:04:15.300 --> 00:04:16.400
This phrase is bad.

00:04:16.400 --> 00:04:17.200
This phrase is good.

00:04:17.340 --> 00:04:26.180
And then it uses that to understand how similar whatever you're looking at is to something like one of these bad phrases.

00:04:26.180 --> 00:04:27.040
Isn't that cool?

00:04:27.040 --> 00:04:27.420
Yeah.

00:04:27.420 --> 00:04:27.920
Very.

00:04:27.920 --> 00:04:33.940
So one of the problems with a lot of the systems out there that are more simple is they just have like explicitly bad words.

00:04:33.940 --> 00:04:44.200
But as you can imagine, there are many, many bad words that you might forget or there's some slightly different way of saying some other thing and they fall through.

00:04:44.200 --> 00:04:46.660
So this one turns out to catch a lot of them.

00:04:46.660 --> 00:04:48.900
And it's also super, super fast.

00:04:48.900 --> 00:04:56.420
So there's another one out there called profanity dash filter, which is more sophisticated than a lot of these, you know, like just are these words in here?

00:04:56.420 --> 00:04:56.800
Checks.

00:04:56.800 --> 00:05:06.200
This one is similar, but because it creates this model and just uses the result, it's actually like 300 to 400 times faster than the other one.

00:05:06.200 --> 00:05:06.620
That's cool.

00:05:06.620 --> 00:05:10.720
If you have 300 to 400 times faster, not percent times, right?

00:05:10.720 --> 00:05:14.880
Like 13 seconds versus 24 milliseconds type of difference.

00:05:14.880 --> 00:05:15.880
That's pretty awesome.

00:05:15.980 --> 00:05:21.200
And the speed really matters if you're, especially if the amount of text you're filtering is huge.

00:05:21.200 --> 00:05:21.500
Right.

00:05:21.500 --> 00:05:23.980
Or a whole bunch of stuff real time or something like that.

00:05:23.980 --> 00:05:25.740
And so it's super simple to use.

00:05:25.740 --> 00:05:27.020
It has basically two functions.

00:05:27.020 --> 00:05:31.600
It's predict whether or not something is bad or give the probability.

00:05:31.840 --> 00:05:35.520
So you can call predict and give it some text and it'll give you like zero one.

00:05:35.520 --> 00:05:37.400
Or you can say, give me the probability.

00:05:37.400 --> 00:05:42.400
And it'll say, we think this is 76.3% bad.

00:05:42.400 --> 00:05:44.480
Do with that what you will.

00:05:44.480 --> 00:05:49.920
So you can take it as black and white or gray and then just decide how gray you'll let it get.

00:05:49.920 --> 00:05:50.160
Okay.

00:05:50.240 --> 00:05:53.000
So I'm like, I'm redoing one of my websites.

00:05:53.000 --> 00:05:57.840
Maybe I'll do this on my own blog posts and make sure that I haven't.

00:05:58.580 --> 00:06:02.420
Just curious to see what my confidence level is that they're clean.

00:06:02.420 --> 00:06:03.300
Yeah, exactly.

00:06:03.300 --> 00:06:05.760
I think a lot of people don't have this problem.

00:06:05.760 --> 00:06:11.280
But if your problem is to take user input and evaluate it for this characteristic, like that would be a complete pain.

00:06:11.280 --> 00:06:11.500
Right.

00:06:11.560 --> 00:06:17.340
And so here's a pip install one-liner sort of thing you can do that will help a lot, I think.

00:06:17.340 --> 00:06:17.580
Yeah.

00:06:17.580 --> 00:06:18.180
Neat.

00:06:18.180 --> 00:06:18.440
Yeah.

00:06:18.440 --> 00:06:19.480
Yes, indeed.

00:06:19.480 --> 00:06:20.060
All right.

00:06:20.060 --> 00:06:20.800
What's the next one?

00:06:20.800 --> 00:06:23.060
Something we've never talked about on this show, right?

00:06:23.060 --> 00:06:27.160
We've actually talked, of course, talked about packaging quite a bit.

00:06:27.160 --> 00:06:38.700
So dealing with packages, if you're dealing with Python a lot, like the difference between a module and a package in the file system and then an installable package that you can distribute,

00:06:38.700 --> 00:06:40.840
that all just becomes second nature.

00:06:40.840 --> 00:06:42.740
And we don't even really think about it anymore.

00:06:42.740 --> 00:06:48.020
But as I'm working with different people and different people are starting to work in Python around you,

00:06:48.020 --> 00:06:51.800
sometimes you have somebody that you need to explain this to.

00:06:51.800 --> 00:06:58.940
And it's hard for me to remember what it was like to not know all this stuff.

00:06:58.940 --> 00:07:04.660
So I bookmarked this article called An Introduction to Python Packages for Absolute Beginners.

00:07:04.940 --> 00:07:18.040
And it's just a nice, gentle discussion about somebody trying to share some code and then describes modules and packages and using packages and installing and what import means and a bunch of stuff like that.

00:07:18.040 --> 00:07:18.560
Yeah.

00:07:18.660 --> 00:07:23.440
So I think this would be good either to hand around or just review before you go explain it to somebody.

00:07:23.440 --> 00:07:23.720
Right.

00:07:23.720 --> 00:07:28.700
We get so excited about jumping in and talking about poetry or pip enf or all these other things.

00:07:28.700 --> 00:07:31.320
And it's just like, wait, what are these?

00:07:31.320 --> 00:07:33.100
You know, when you're new, it's like, what are these things?

00:07:33.100 --> 00:07:34.980
Like, how do I make a package?

00:07:34.980 --> 00:07:36.860
You know, how do I share it?

00:07:36.860 --> 00:07:41.420
You know, people probably start out with just like one giant Python file.

00:07:41.420 --> 00:07:45.260
And like, that's the whole, the whole app is just crammed into the one file even.

00:07:45.260 --> 00:07:45.480
Right.

00:07:45.600 --> 00:07:51.620
And people share the code by just emailing it around or copying it into different repos and stuff.

00:07:51.620 --> 00:07:54.000
And there's, yeah, there are better ways.

00:07:54.000 --> 00:08:03.720
To me, it's a little annoying that the word package has multiple meanings because it's Python calls just a directory with an init in it.

00:08:03.720 --> 00:08:04.840
That's a package.

00:08:04.840 --> 00:08:08.780
But that's not what PyPI is full of.

00:08:08.780 --> 00:08:09.060
Right.

00:08:09.060 --> 00:08:10.240
Distributions.

00:08:10.240 --> 00:08:12.060
Like wheels and all that stuff, right?

00:08:12.060 --> 00:08:13.660
Like, yeah, a whole nother level.

00:08:13.760 --> 00:08:16.460
I do agree that those are like oddly the same and different.

00:08:16.460 --> 00:08:17.020
Yeah.

00:08:17.020 --> 00:08:17.340
Yeah.

00:08:17.340 --> 00:08:18.100
Definitely confusing.

00:08:18.100 --> 00:08:18.700
So this is good.

00:08:18.700 --> 00:08:24.280
So if you're confused about how your app is working, we know a company that can help, right, Brian?

00:08:24.280 --> 00:08:24.940
Yes, we do.

00:08:24.940 --> 00:08:25.400
DataDog.

00:08:25.400 --> 00:08:27.840
So DataDog sponsoring the show, as I said at the opening.

00:08:27.840 --> 00:08:34.820
They're a cloud scale monitoring platform that brings together all your metrics, logs, distributed traces all into one place.

00:08:35.300 --> 00:08:48.640
And it will auto instrument things like Django or Flask or Postgres and let you track requests across those different pieces of infrastructure and put them all back together to know why it was slow, where it was working, things like that.

00:08:48.640 --> 00:08:49.280
So that's pretty awesome.

00:08:49.280 --> 00:08:53.040
Check them out at pythonbytes.fm/DataDog.

00:08:53.200 --> 00:08:56.940
Go do a free trial and they will send you a cool DataDog t-shirt.

00:08:56.940 --> 00:08:59.060
So definitely check them out.

00:08:59.060 --> 00:08:59.880
It helps support the show.

00:08:59.880 --> 00:09:00.960
Plus the t-shirts are cool.

00:09:00.960 --> 00:09:02.060
And the t-shirts are very cool.

00:09:02.060 --> 00:09:03.120
They have a cute little dog on them.

00:09:03.120 --> 00:09:09.300
Now, I'm going to bring up something on here that we don't spend a whole lot of time on.

00:09:09.300 --> 00:09:11.300
And maybe it's even a little bit controversial.

00:09:11.300 --> 00:09:11.880
What do you think?

00:09:11.880 --> 00:09:13.520
I'm looking forward to talking about this.

00:09:13.520 --> 00:09:14.600
Yeah, I figured you are.

00:09:14.600 --> 00:09:16.280
I figured you have an opinion one way or the other.

00:09:16.360 --> 00:09:25.260
So the idea is in Python, we can usually get away with replacing our dependencies.

00:09:25.260 --> 00:09:36.980
Like if we're talking to a database or a web service, we can kind of cancel that out so we can test our code by doing like some sort of patch operation or something to that effect.

00:09:36.980 --> 00:09:37.180
Right.

00:09:37.180 --> 00:09:38.680
We can get it out of the way.

00:09:38.680 --> 00:09:53.640
But this guy named Yasha Gutzur, hopefully I got that closely right, sent us a message that said, hey, I've been reviewing all of the Python dependency injection and IOC inversion control containers around Python.

00:09:53.640 --> 00:10:01.240
And I know that some folks say it's not even necessary, but on large apps, I think there's a lot of value in making your dependencies more explicit.

00:10:01.240 --> 00:10:01.720
Interesting.

00:10:01.720 --> 00:10:02.080
Yeah.

00:10:02.080 --> 00:10:04.700
So he sent us a big long list of all the options, basically.

00:10:04.700 --> 00:10:07.260
And he did a bunch of good research for us.

00:10:07.260 --> 00:10:07.520
Awesome.

00:10:07.520 --> 00:10:07.780
Yeah.

00:10:07.780 --> 00:10:10.920
So I'll just read off a couple of them here.

00:10:10.920 --> 00:10:12.040
We got five or six.

00:10:12.040 --> 00:10:19.920
So we have one called dependency injector, which apparently requires some tricks to get installed on Windows, but he couldn't get it quite working.

00:10:19.920 --> 00:10:21.820
But it looks pretty good.

00:10:21.820 --> 00:10:23.520
I'm kind of mediocre on that one.

00:10:23.520 --> 00:10:26.660
There's injector, which is fairly Java-esque.

00:10:26.660 --> 00:10:33.660
There's pinject, probably pinject, P-I-N-J-E-C-T, something like that.

00:10:34.360 --> 00:10:39.820
And this one had kind of gone unmaintained for about five years, a long time.

00:10:39.820 --> 00:10:44.280
But now there's new folks working on it, so that's kind of cool, and it seems like it's doing a lot.

00:10:44.280 --> 00:10:50.060
There's Python inject, which has got some really nice testing features.

00:10:50.060 --> 00:10:53.200
It's got like built-in mocking stuff and things like that.

00:10:53.460 --> 00:10:55.400
Are you starting to notice a similarity in the name?

00:10:55.400 --> 00:10:56.260
In the naming?

00:10:56.260 --> 00:10:57.400
Yeah.

00:10:58.300 --> 00:11:05.720
There's another one that's just here more for a complete mistake, DIPy, but it only works on Python 3.4, apparently.

00:11:05.720 --> 00:11:08.360
So I appreciate the comment here.

00:11:08.360 --> 00:11:12.160
It's like, you know, this is a legacy, so I can't really be touching on this.

00:11:12.160 --> 00:11:12.880
Like, this is no good.

00:11:12.880 --> 00:11:15.580
And then the next two, I think, are really quite good.

00:11:15.580 --> 00:11:15.820
Okay.

00:11:15.820 --> 00:11:26.340
There's Serum, which I think actually is a pretty interesting thing to look at, because what it does is it primarily is driven through class decorators.

00:11:26.340 --> 00:11:27.480
Okay?

00:11:27.560 --> 00:11:35.280
So what you do is you go to, like, some class here, and you say, this class is a dependency.

00:11:35.280 --> 00:11:39.120
So you put an add dependency on to the class definition.

00:11:39.120 --> 00:11:46.500
And then later on, you can put an add inject on top of either a function call or a class.

00:11:46.500 --> 00:11:58.040
And if the class has, like, say, like a log field, a class-level log field, it will automatically be set to an instance of that dependency based on the type annotation.

00:11:58.040 --> 00:12:03.960
There's an interesting way that it kind of uses type annotations and class decorators to link that back together.

00:12:03.960 --> 00:12:04.380
Yeah.

00:12:04.380 --> 00:12:04.960
Okay.

00:12:04.960 --> 00:12:05.320
Okay.

00:12:05.320 --> 00:12:08.240
And then the final one is this thing called HAPS.

00:12:08.240 --> 00:12:15.520
And HAPS is pretty cool, and it's really lightweight and quite simple, also based on type annotations.

00:12:15.520 --> 00:12:19.640
So a lot of them are taking advantage of the, I think it's probably 3.6, either 3.5 or 3.6.

00:12:19.640 --> 00:12:22.700
But I think it's 3.6 because of some of the ways it's using type annotations.

00:12:22.700 --> 00:12:31.520
But the point is using the modern features of Python 3 to help figure out a lot of the configuration and how stuff wires together.

00:12:31.520 --> 00:12:31.900
Okay.

00:12:31.900 --> 00:12:37.280
That's the survey that Yosha gave us, and thank you for that.

00:12:37.280 --> 00:12:37.740
That was cool.

00:12:37.740 --> 00:12:42.380
Now, you want to have a quick chat about whether Python needs dependency injection?

00:12:42.380 --> 00:12:43.500
What do you think?

00:12:43.500 --> 00:12:48.500
I'm still confused as to what the problem is that it's trying to solve, is my thing.

00:12:48.500 --> 00:12:48.980
I hear you.

00:12:48.980 --> 00:12:53.580
And I think, let me try to talk about the other side, although I find myself not doing this very often.

00:12:53.580 --> 00:12:57.300
So for what it's worth, I don't do dependency injection a lot.

00:12:57.300 --> 00:13:00.900
So I think the fundamental, let's do it a couple steps.

00:13:00.960 --> 00:13:10.560
I think the fundamental starting point is it's trying to write object-oriented Python or even functions following the open-closed principle, which is one of the solid principles.

00:13:10.560 --> 00:13:13.080
And it's pretty interesting, this principle.

00:13:13.080 --> 00:13:20.720
It says that software entities like classes and functions should be open for extension but closed for modification, which is like, what the heck does that mean?

00:13:21.080 --> 00:13:29.920
Basically, I should be able to change the behavior of this class or this function without touching the source code to modify it, which kind of sounds like, wait, how do you do that?

00:13:29.920 --> 00:13:30.720
How is that possible?

00:13:31.160 --> 00:13:34.540
But imagine it has a logging feature.

00:13:34.540 --> 00:13:41.860
Instead of just internally creating one, if you could pass in the logger, you could pass in different loggers changing the behavior of how it logs.

00:13:41.860 --> 00:13:44.100
So open-closed principle, that's how it works.

00:13:44.100 --> 00:13:49.120
I think the general motivation for all of these frameworks is they're like, that's cool.

00:13:49.120 --> 00:13:50.020
I want to do that.

00:13:50.020 --> 00:13:54.860
It's good for testing because I could pass in a fake logger or a mock database.

00:13:54.860 --> 00:13:57.780
I could pass that in and not touch the database.

00:13:58.780 --> 00:14:02.000
And I think that's generally a good feature, a good way to do things.

00:14:02.000 --> 00:14:10.580
The problem is if you do that at low-level stuff and at all the different layers of your app, at the top, you've got to pass 20 things to the top-level things.

00:14:10.580 --> 00:14:14.520
So it can distribute them down as it creates all the objects further down the graph, right?

00:14:14.520 --> 00:14:20.940
So then people have come up with IOC containers, which get registered for when I need one of these.

00:14:20.940 --> 00:14:22.120
I really give it one of those.

00:14:22.120 --> 00:14:25.380
And then I create this object by giving it three of these things at once.

00:14:25.520 --> 00:14:32.240
And that starts to get really hard in my mind to know, like, okay, what is being done here?

00:14:32.240 --> 00:14:35.080
Like, I see a bunch of abstract types and I can't even tell.

00:14:35.080 --> 00:14:39.040
An example of, like, you don't know what database you're going to use.

00:14:39.040 --> 00:14:45.660
Another, you can use the injection thing, but it kind of ripples through a whole bunch of layers of code.

00:14:45.660 --> 00:14:46.280
It does.

00:14:46.420 --> 00:14:47.680
The part that I don't like.

00:14:47.680 --> 00:15:00.020
Whereas another way to do this is to kind of bypass all of the middle stuff and at a top level have, and like Flask, I think Flask does this sort of a thing.

00:15:00.260 --> 00:15:11.300
And a lot, this is a common design is to, you define, instantiate the real objects at a, like an application level and just set those where they need to be set.

00:15:11.300 --> 00:15:13.820
So there's like a, whatever the real database is.

00:15:13.820 --> 00:15:14.180
Right.

00:15:14.180 --> 00:15:18.680
Go look up the service for the database and everybody can ask that thing to give it the database, right?

00:15:18.680 --> 00:15:25.200
And then everybody just uses the same interface and we don't need to pass it through all the levels of constructors and stuff.

00:15:25.260 --> 00:15:27.160
It can just kind of bypass all of that.

00:15:27.160 --> 00:15:31.260
I guess then, because that's how I generally do things.

00:15:31.260 --> 00:15:36.600
And then for testing, yeah, I'm okay with patching and monkey patching and stuff like that.

00:15:36.600 --> 00:15:37.340
I hear you.

00:15:37.340 --> 00:15:45.940
I think in Python, it is certainly something that's open more for debate because we do have these alternative ways to accomplish the same thing like monkey patching.

00:15:45.940 --> 00:15:48.120
Now, I don't know.

00:15:48.120 --> 00:15:51.220
I'm kind of a fan of the open close principle in general,

00:15:51.220 --> 00:15:55.720
but I do think it can just become like too much when you put it all together.

00:15:55.720 --> 00:16:00.560
And certainly I've worked on some applications that did this all over the place.

00:16:00.560 --> 00:16:05.400
And it was some of the most frustrating code I've ever had to like work through because it was just like every step.

00:16:05.400 --> 00:16:13.560
You're like, I have, there's four things working together and I don't know what any of them are right now because of some configuration setting somewhere other than that.

00:16:13.560 --> 00:16:14.220
So I don't know.

00:16:14.220 --> 00:16:16.200
I'm kind of, I'm on the fence.

00:16:16.360 --> 00:16:23.380
Like some parts of this I think are cool and some I think can go too far, but I guess, you know, check out HAPS if this kind of stuff is interesting to you.

00:16:23.380 --> 00:16:24.720
It is, it is pretty well done.

00:16:24.720 --> 00:16:31.340
I think that one of the places for it is if people are really used to using this kind of a model and then coming to Python.

00:16:31.340 --> 00:16:32.760
Yeah, you can do it here too.

00:16:32.760 --> 00:16:33.020
Yeah.

00:16:33.020 --> 00:16:35.280
It's just, I'm not, I'm not sure I'm there.

00:16:35.280 --> 00:16:35.580
Yeah.

00:16:35.580 --> 00:16:43.680
I think there's simpler things in IOC containers, but this podcast is probably a little short if we're going into them, but it's certainly an interesting thing to think about.

00:16:43.680 --> 00:16:45.180
And here's a bunch of options.

00:16:45.460 --> 00:16:45.600
Yep.

00:16:45.600 --> 00:16:46.020
Cool.

00:16:46.020 --> 00:16:52.760
You know, after all that, Brian, I feel like I just need something gentle, like a gentle conversation about like a soft, fuzzy animal.

00:16:52.760 --> 00:16:53.800
Yeah.

00:16:53.800 --> 00:16:56.080
Like a gentle introduction to pandas.

00:16:56.080 --> 00:16:56.600
Yes.

00:16:56.600 --> 00:16:58.440
Well, maybe not an animal, but yeah, something gentle.

00:16:58.440 --> 00:16:59.340
Tell us about pandas.

00:16:59.420 --> 00:17:05.580
So this is another kind of a newbie thing, but I, we're starting to use pandas data frames at work.

00:17:05.580 --> 00:17:14.680
And I kind of, I really kind of needed a pretend I'm just starting out, which I am and kind of tell me how these things work.

00:17:14.680 --> 00:17:23.340
And so this is a, it's called a gentle introduction to pandas, but it's really a gentle introduction to the data structures, series and data frame.

00:17:23.660 --> 00:17:25.360
The series are interesting.

00:17:25.360 --> 00:17:29.020
I think it's just a precursor to try to jump you into data frames.

00:17:29.340 --> 00:17:32.000
That's where the real fun gets, starts to happen.

00:17:32.000 --> 00:17:36.540
Goes through about a half an article talking about arrays, series.

00:17:36.540 --> 00:17:39.140
How do you create series from arrays and dictionaries?

00:17:39.400 --> 00:17:47.680
And I didn't know you could create a, a series from, from just a scaler and give it a bunch, a different index and it'll like fill it in.

00:17:47.680 --> 00:17:48.380
That's pretty cool.

00:17:48.380 --> 00:17:49.080
Oh, that is cool.

00:17:49.080 --> 00:17:49.620
Yeah.

00:17:49.620 --> 00:17:56.940
But then it jumps into data frames and then talks about sorting and slicing and how do you select things by label or position.

00:17:56.940 --> 00:18:05.820
And then what, one of the things and how easy it is to get the statistics on columns and then how to get things in and out of data frames.

00:18:05.820 --> 00:18:07.480
So importing and exporting.

00:18:07.760 --> 00:18:17.500
And then, you know, where you take it from there is, depends on your problem space, but this is kind of a really good, why do we call these things data frames and why do we care about them?

00:18:17.500 --> 00:18:20.500
If you need to understand them, this is a decent article.

00:18:20.500 --> 00:18:20.740
Yeah.

00:18:20.740 --> 00:18:25.940
If you need to understand them in 15 minutes, this is kind of a no fluff, keep it simple one.

00:18:25.940 --> 00:18:26.240
Yeah.

00:18:26.240 --> 00:18:28.000
Nice little article by Wilson Boussaka.

00:18:28.000 --> 00:18:28.720
Well done.

00:18:28.720 --> 00:18:30.040
Let's see.

00:18:30.040 --> 00:18:34.980
Medium tells me it's a five minute read, but I bet Medium's not taking into account the code.

00:18:34.980 --> 00:18:36.300
So 15 minutes.

00:18:36.300 --> 00:18:36.720
How about that?

00:18:36.720 --> 00:18:37.920
Yeah, I think so.

00:18:37.920 --> 00:18:38.140
Right.

00:18:38.140 --> 00:18:44.000
So this last one I have for you, Brian, I think, I think it's going to be a little bit of a shock.

00:18:44.000 --> 00:18:50.340
It'll come across a little bit weird at first, but the more you look at it, the more it starts to sound appealing, let's say.

00:18:50.340 --> 00:18:50.660
Yeah.

00:18:50.660 --> 00:18:50.960
All right.

00:18:50.960 --> 00:18:52.040
So I'm going to give you some advice.

00:18:52.040 --> 00:18:53.100
I'm going to tell you about it.

00:18:53.100 --> 00:18:58.500
So the advice, you know, you also get all sorts of advice, like don't format your code like this.

00:18:58.500 --> 00:19:02.120
Don't have a bunch of multiple.

00:19:02.120 --> 00:19:07.200
If this is equal to this value and that value and that value, maybe do an end test.

00:19:07.260 --> 00:19:10.400
So there's like sort of Pythonic ways to do conditionals and whatnot.

00:19:10.400 --> 00:19:18.120
The advice here is to never, not almost never, says don't use the greater than sign in programming.

00:19:18.120 --> 00:19:18.780
Yeah.

00:19:18.780 --> 00:19:19.460
It's crazy, right?

00:19:19.520 --> 00:19:21.180
It seems like kind of a bold statement.

00:19:21.180 --> 00:19:22.800
I'm like, well, we have it.

00:19:22.800 --> 00:19:24.200
It must be useful somewhere.

00:19:24.200 --> 00:19:25.420
It must be useful.

00:19:25.420 --> 00:19:26.980
And why would we not want to use it?

00:19:26.980 --> 00:19:32.320
So this is an article by a good friend of mine, Llewellyn Falco, who I've known for a long time.

00:19:32.320 --> 00:19:36.500
But someone else sent me this article, which I thought was a pretty interesting coincidence.

00:19:36.500 --> 00:19:45.100
And Llewellyn has a really interesting way of like looking at straightforward stuff and then just getting it down to its essence.

00:19:45.100 --> 00:19:48.220
So he says, like, let's look at this problem.

00:19:48.300 --> 00:19:54.780
Let's suppose I want to check whether a number, let's call it x, it's a variable, is between 5 and 10.

00:19:54.780 --> 00:19:58.160
There are a lot of ways that we can do this.

00:19:58.160 --> 00:20:02.140
We could say x greater than 5 and 10 greater than x.

00:20:02.140 --> 00:20:06.260
Or we could say x greater than 5 and x less than 10, right?

00:20:06.260 --> 00:20:07.480
Those are equivalent.

00:20:07.480 --> 00:20:11.040
But why should you choose one over the other?

00:20:11.040 --> 00:20:15.200
Well, he lists off these six different ways of doing this.

00:20:15.200 --> 00:20:16.400
He says, actually, here's all the ways.

00:20:16.400 --> 00:20:17.120
Oh, no, wait.

00:20:17.200 --> 00:20:18.260
Look, one of them is wrong.

00:20:18.260 --> 00:20:20.420
Go back and figure out which one is wrong.

00:20:20.420 --> 00:20:21.860
And it's like not very obvious.

00:20:21.860 --> 00:20:25.580
You know, you kind of got to go through and think through every little bit.

00:20:25.580 --> 00:20:26.520
All right.

00:20:26.520 --> 00:20:31.560
So he says, look, if you remove the greater than sign, there's actually only two ways to say this.

00:20:32.120 --> 00:20:36.120
x less than 10 and 5 less than x, which is kind of weird.

00:20:36.120 --> 00:20:39.600
Or 5 less than x and x less than 10.

00:20:39.600 --> 00:20:48.040
So in that last one, it's cool because the variable you're trying to test between 5 and 10 is literally between the 5 and the 10 in that statement.

00:20:48.040 --> 00:20:50.840
Like it's in text, it's between, and it's actually between.

00:20:50.840 --> 00:20:51.240
Yeah.

00:20:51.380 --> 00:20:57.320
So here you can test like this containment interval bit completely with no greater than.

00:20:57.320 --> 00:20:58.540
That's how I code.

00:20:58.540 --> 00:21:06.840
I think of, especially, well, especially with numbers, I think of the, that all of the comparisons need to kind of be on the number line.

00:21:06.840 --> 00:21:07.300
Yes.

00:21:07.400 --> 00:21:08.800
You can think about them easier.

00:21:08.800 --> 00:21:15.480
I've never really seen it as it put in place as a rule, kind of a rule of thumb of just don't use the greater than sign.

00:21:15.480 --> 00:21:15.700
Yeah.

00:21:15.700 --> 00:21:16.380
It's really interesting.

00:21:16.380 --> 00:21:22.820
And this analogy back to the number line is perfect because it's like, well, where do you want the variable to be relative to those?

00:21:22.820 --> 00:21:27.120
So if you want it to be between, then as you say, like 5 less than x, x less than 10.

00:21:27.120 --> 00:21:27.440
Right?

00:21:27.440 --> 00:21:28.460
So it's between.

00:21:28.460 --> 00:21:32.280
If you want to test that it's outside there, you could do the same thing.

00:21:32.280 --> 00:21:34.820
x less than 5 or 10 less than x.

00:21:34.820 --> 00:21:36.820
And you put the variable outside the numbers.

00:21:36.820 --> 00:21:37.520
Right?

00:21:37.520 --> 00:21:45.540
So you can do this number line sort of relative bit with both, you know, and and or and containment and not contained in and things like that.

00:21:45.540 --> 00:21:50.820
We'd kind of be remiss if we didn't mention that this article is referencing all programming languages.

00:21:50.820 --> 00:21:56.120
If you're doing Python, of course, you would just say 5 is less than x is less than 10.

00:21:56.120 --> 00:21:57.480
You can, you don't need the and.

00:21:57.480 --> 00:21:57.820
Nice.

00:21:57.820 --> 00:22:02.460
And also somebody said, okay, I'm all for, I follow you on this.

00:22:02.460 --> 00:22:03.120
This is great.

00:22:03.120 --> 00:22:05.940
And I'm with you.

00:22:05.940 --> 00:22:10.960
But how do you say I would like all the numbers greater than one without the greater than sign?

00:22:10.960 --> 00:22:15.860
And so the answer is, of course, one less than x.

00:22:15.860 --> 00:22:16.720
Yeah.

00:22:16.720 --> 00:22:21.480
There's times where it's a little, that's why it's not like it's more of a rule of thumb.

00:22:21.480 --> 00:22:22.100
Yeah.

00:22:22.140 --> 00:22:25.000
I think because there's times where it just doesn't look right.

00:22:25.000 --> 00:22:27.020
And you kind of, you have to go for maintenance.

00:22:27.020 --> 00:22:30.380
If it, if it just looks weird, then change it.

00:22:30.380 --> 00:22:32.820
I brought this in because I thought it was interesting.

00:22:32.820 --> 00:22:35.500
And like when I first read it, I'm like, well, that's dumb advice.

00:22:35.500 --> 00:22:36.120
What is this?

00:22:36.120 --> 00:22:37.360
You know what I mean?

00:22:37.360 --> 00:22:38.100
And I read it.

00:22:38.100 --> 00:22:41.260
I'm like, actually, you know, this makes a lot of sense a lot of the time.

00:22:41.260 --> 00:22:42.640
But it's, I agree.

00:22:42.640 --> 00:22:45.300
If you have one thing, you want to say x is greater than one.

00:22:45.300 --> 00:22:48.760
You know, don't twist around so you don't have to have the greater than sign.

00:22:48.760 --> 00:22:50.840
Just like say the most straightforward thing.

00:22:50.840 --> 00:22:54.740
But if you're doing more complicated comparisons, then I think it's worthwhile.

00:22:55.060 --> 00:22:55.220
Yeah.

00:22:55.220 --> 00:23:01.480
Like I would say, like, for instance, a series of if clauses, if you have, and you're not

00:23:01.480 --> 00:23:07.040
really testing both ends, if you're doing like, if x is greater than the max, then do something.

00:23:07.040 --> 00:23:11.580
And if all the comparisons have x on the left, I wouldn't change it just because of this.

00:23:11.580 --> 00:23:12.560
But, you know, anyway.

00:23:12.560 --> 00:23:13.000
All right, Brian.

00:23:13.000 --> 00:23:14.960
Well, that's it for all of our main topics.

00:23:14.960 --> 00:23:18.000
I got a few extras to share with everyone while we're here.

00:23:18.000 --> 00:23:19.140
Just really quick and short things.

00:23:19.140 --> 00:23:21.500
And of course, not be forgotten as our joke.

00:23:21.500 --> 00:23:23.140
But you got any extras to share with everyone?

00:23:23.260 --> 00:23:28.020
I did mention last time that I was having some issues with pythontesting.net.

00:23:28.020 --> 00:23:29.340
I think I mentioned that.

00:23:29.340 --> 00:23:31.260
But with SSL and stuff.

00:23:31.260 --> 00:23:33.720
But that's all resolved and fixed.

00:23:33.720 --> 00:23:34.420
Wait, wait, wait.

00:23:34.420 --> 00:23:40.080
So if I go over here and I pull this up in Chrome, is it going to tell me that it's secure?

00:23:40.080 --> 00:23:40.700
It should.

00:23:40.700 --> 00:23:41.260
Nice.

00:23:41.260 --> 00:23:43.760
Yeah, testing code over SSL.

00:23:43.760 --> 00:23:44.060
Beautiful.

00:23:44.060 --> 00:23:47.260
It's now, it's still kind of a WordPress thing is what I use.

00:23:47.260 --> 00:23:48.640
And I'm not thrilled with that.

00:23:48.640 --> 00:23:52.280
So I have a side project going on to convert that to something else.

00:23:52.760 --> 00:23:54.140
But it's not urgent anymore.

00:23:54.140 --> 00:23:54.920
Yeah, that's good.

00:23:54.920 --> 00:23:59.060
Well, you'll have to give us the full report once you get it all fixed up.

00:23:59.060 --> 00:23:59.340
Okay.

00:23:59.340 --> 00:24:01.160
So you said you got a bunch of stuff for us.

00:24:01.160 --> 00:24:01.540
I do.

00:24:01.540 --> 00:24:02.340
I'll go through them quick.

00:24:02.340 --> 00:24:05.600
First of all, there's a new Python podcast, which is pretty exciting.

00:24:05.600 --> 00:24:08.600
And this one is focused on teaching Python.

00:24:08.600 --> 00:24:10.580
And do you know what the name of it is?

00:24:10.580 --> 00:24:12.320
I think it's probably teaching Python.

00:24:12.560 --> 00:24:13.280
Yeah, it is.

00:24:13.280 --> 00:24:18.460
So Teaching Python is by Kelly Perdez and Sean Tibor.

00:24:18.460 --> 00:24:20.140
Sorry about messing up the names.

00:24:20.140 --> 00:24:21.200
But they're doing a podcast.

00:24:21.200 --> 00:24:25.680
These are two middle school teachers who are learning and teaching Python to their students

00:24:25.680 --> 00:24:28.200
and go, you know, basically documenting that journey.

00:24:28.200 --> 00:24:32.440
So if you're interested in that, especially if you're a teacher or you work with kids,

00:24:32.440 --> 00:24:34.740
I think this will be really, really helpful for you.

00:24:34.740 --> 00:24:35.360
So you can check that out.

00:24:35.440 --> 00:24:40.620
I'm about halfway through their backlog so far, and I really like it so far.

00:24:40.620 --> 00:24:41.560
Yeah, they're doing a nice job.

00:24:41.560 --> 00:24:49.000
One of the things that had kept people from using GitHub for their private work was that

00:24:49.000 --> 00:24:52.600
you had to pay for private repositories on GitHub, no matter what.

00:24:52.600 --> 00:24:52.940
Yes.

00:24:52.940 --> 00:24:53.360
Right.

00:24:53.360 --> 00:24:57.660
So people would use Bitbucket because Bitbucket had free private repositories.

00:24:57.660 --> 00:25:02.060
Well, GitHub decided we're also going to have free private repositories.

00:25:02.060 --> 00:25:05.140
So if you're working on projects that they have to stay private,

00:25:05.240 --> 00:25:08.880
you just want them private, you can now use GitHub without paying anything.

00:25:08.880 --> 00:25:10.920
There's been some weird reactions to it,

00:25:10.920 --> 00:25:15.860
but they're just sort of following the model of Bitbucket and GitLab now.

00:25:15.860 --> 00:25:18.560
So I don't think there's anything weird going on.

00:25:18.560 --> 00:25:18.980
Exactly.

00:25:18.980 --> 00:25:21.640
Competition is a good thing, and here we have it.

00:25:21.640 --> 00:25:23.300
So it's not like entirely free.

00:25:23.300 --> 00:25:25.780
It's not like GitHub decided they're not going to make money anymore.

00:25:25.780 --> 00:25:29.300
You can only have three contributors to the private repository,

00:25:29.300 --> 00:25:31.320
and so there's limits and things like that.

00:25:31.320 --> 00:25:34.220
But still pretty cool for most things.

00:25:34.220 --> 00:25:34.560
Yep.

00:25:34.560 --> 00:25:34.760
All right.

00:25:35.040 --> 00:25:39.700
Also, very quickly, some early details about Europython are available,

00:25:39.700 --> 00:25:41.400
and it's looking pretty sweet.

00:25:41.400 --> 00:25:42.220
I'd love to go.

00:25:42.220 --> 00:25:43.320
I don't know if I'll be able to.

00:25:43.320 --> 00:25:43.900
Yeah, me too.

00:25:43.900 --> 00:25:45.660
Yeah, so they just announced Europython.

00:25:45.660 --> 00:25:51.560
It's going to be in Basel, Switzerland, July 8th to 14th, and it looks great.

00:25:51.560 --> 00:25:55.020
So I put a link to the conference site there.

00:25:55.020 --> 00:25:58.040
I don't think they have a call for papers or anything like that out yet,

00:25:58.040 --> 00:25:59.260
but it should be out pretty soon.

00:25:59.360 --> 00:26:06.040
Another thing that has been lacking in the world is good data center support in Africa.

00:26:06.780 --> 00:26:13.380
So I know this because I use AWS to deliver the video course content,

00:26:13.380 --> 00:26:14.700
like actual the videos.

00:26:15.060 --> 00:26:20.660
And I have streaming servers all over the place, like in Brazil or Mumbai or whatever,

00:26:20.660 --> 00:26:23.440
but there's just no way to do that in Africa.

00:26:23.440 --> 00:26:32.340
So the big news is there's an AWS data center coming to South Africa, which is pretty cool for anyone that wants to be closer to that part of the world.

00:26:32.780 --> 00:26:36.960
And finally, Pandas is dropping legacy support.

00:26:36.960 --> 00:26:39.400
No more Python 2 in Pandas.

00:26:39.400 --> 00:26:40.080
Oh, cool.

00:26:40.080 --> 00:26:42.500
Yeah, and that's coming out like this month.

00:26:42.500 --> 00:26:43.900
So it should be good.

00:26:43.900 --> 00:26:47.760
Yeah, this is the year that a ton of projects are dropping Python 2.

00:26:47.760 --> 00:26:48.540
Yeah, for sure.

00:26:48.540 --> 00:26:51.720
So one more major thing.

00:26:51.720 --> 00:26:53.160
We already covered how cool Pandas is.

00:26:53.160 --> 00:26:55.980
It's not going to support legacy Python anymore.

00:26:55.980 --> 00:26:56.880
All right.

00:26:56.880 --> 00:26:58.700
You ready for the joke?

00:26:58.700 --> 00:26:59.000
Yeah.

00:26:59.000 --> 00:26:59.900
Can I click on it now?

00:26:59.900 --> 00:27:00.620
You can click on it.

00:27:00.660 --> 00:27:02.940
This is a visual one, but I can describe it to you folks.

00:27:02.940 --> 00:27:09.720
Now, I just got to do a quick little bit of history here for people who maybe have not seen Harry Potter.

00:27:09.720 --> 00:27:11.240
So this is the Harry Potter joke.

00:27:11.240 --> 00:27:15.480
And there's a point in the Harry Potter movie, I think this might be the first one,

00:27:15.480 --> 00:27:21.680
where Harry Potter has to get on this like long table and is battling, I don't know, someone, something.

00:27:21.680 --> 00:27:23.840
And all the other students are standing around.

00:27:23.840 --> 00:27:26.880
And somebody like conjures a snake, a serpent.

00:27:27.860 --> 00:27:35.160
And in the real show, Harry starts speaking to the thing in its native tongue, which apparently is a freaky thing to do.

00:27:35.160 --> 00:27:36.860
And people were all freaked out.

00:27:36.860 --> 00:27:40.120
And it was called a parcel tongue, something like that, right?

00:27:40.120 --> 00:27:41.060
That he could speak snake.

00:27:41.060 --> 00:27:43.080
So with that, here's the joke.

00:27:43.460 --> 00:27:46.780
So there's a picture, Harry's fighting the snake in that environment.

00:27:46.780 --> 00:27:50.980
And he says, import OS, current path equals OS, get current working to her.

00:27:50.980 --> 00:27:54.260
And just start speaking out Python commands at the snake.

00:27:54.260 --> 00:27:58.080
And Hermione says, I didn't know Harry spoke Python.

00:27:58.080 --> 00:28:02.400
And Ron Weasley says, yeah, he's a parser tongue.

00:28:02.400 --> 00:28:05.400
That's terrible.

00:28:05.400 --> 00:28:06.540
It's really bad.

00:28:06.540 --> 00:28:07.400
It's really bad.

00:28:07.400 --> 00:28:08.600
But there it is.

00:28:08.720 --> 00:28:10.220
And Nick Spirit sent that to us.

00:28:10.220 --> 00:28:13.380
So thank you, Nick, for finding that joke and letting us share it here.

00:28:13.380 --> 00:28:14.420
Yeah, very nerdy.

00:28:14.420 --> 00:28:14.800
Yep.

00:28:14.800 --> 00:28:15.800
He's a parser tongue.

00:28:15.800 --> 00:28:18.840
Well, I think we're going to leave it at that, Brian.

00:28:18.840 --> 00:28:19.800
Thanks for being here.

00:28:19.800 --> 00:28:20.740
Yeah, thank you.

00:28:20.740 --> 00:28:21.200
Yeah, bye.

00:28:21.200 --> 00:28:21.420
Bye.

00:28:21.720 --> 00:28:23.320
Thank you for listening to Python Bytes.

00:28:23.320 --> 00:28:25.860
Follow the show on Twitter via at Python Bytes.

00:28:25.860 --> 00:28:28.740
That's Python Bytes as in B-Y-T-E-S.

00:28:28.740 --> 00:28:32.160
And get the full show notes at pythonbytes.fm.

00:28:32.160 --> 00:28:36.500
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:28:36.500 --> 00:28:39.200
We're always on the lookout for sharing something cool.

00:28:39.200 --> 00:28:42.600
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:28:42.600 --> 00:28:46.120
Thank you for listening and sharing this podcast with your friends and colleagues.

