Write Pythonic Code Like a Seasoned Developer Transcripts
Chapter: Foundational Concepts
Lecture: Multiple tests against a single variable
Login or
purchase this course
to watch this video and the rest of the course contents.
0:01
Now let's talk about multiple tests against a single variable.
0:04
What do I mean by that?
0:06
Here is an example, suppose we have an enumeration of moves,
0:10
North, South, East, West, North-East, South-West, things like that,
0:14
and we would like to test is this a horizontal or vertical move
0:18
or is it a diagonal move?
0:20
So somehow we have received a move called "m",
0:23
from somewhere maybe this is in a game or something,
0:26
and we want to check is it one of the direct, vertical or horizontal ones
0:30
so we would say "if m is North, or if it's South, or if it's West, or if it's East,
0:35
then we are going to match this case."
0:37
So this is very common in many languages but in Python,
0:40
we'll see there is a more Pythonic way of doing things.
0:43
So here we are in PyCharm and we have basically the situation I just described.
0:48
You can see we are in our moves enumeration
0:50
and it has these various moves,
0:52
the four horizontal-vertical ones and the four diagonal ones,
0:56
and it even has a parse method here,
0:58
parse static method and we are going through
1:01
and we are actually checking hey if we are given a text
1:04
and the text lower case version is "w"
1:09
then we are going to parse that to West, if it's "e" then it's East,
1:13
"nw" is North-West and so on.
1:15
Now we'll see if we can actually improve on this as well
1:18
but that's not the point of this conversation,
1:21
OK, so we are going to run our code
1:22
and it's going to ask for which direction we want to move,
1:25
North, South, East, West and so on
1:26
and we'll use that parse method you just saw.
1:28
If it's something it doesn't understand
1:30
it returns None and as we already discussed
1:32
we check if it is None, then we bail or print it out
1:36
so just you can see what the parse did as and
1:37
and then here is this code that we have before.
1:42
So, let's first run this to make sure it works,
1:44
OK, "which direction you want to move?"
1:45
Let's go South-West, move South-West was parsed,
1:49
hey that's a diagonal move;
1:50
we'll try another one, let's try North. North, that's a direct move,
1:54
maybe the name is a little off but you get the idea.
1:57
So let's write in more Pythonic version here.
2:04
recall in Python that if we have a collection,
2:08
like a set or something like that,
2:10
if we say "s = {1,2,9,11}", we can check for containment
2:17
and in this set using the "n" keyword,
2:20
so if we have "v = 11", we could ask we could say "print v in s"
2:27
and because 11 is in the set it should come back and say yes,
2:31
so let's just say something here, True, yes it's in there.
2:34
We change this to 12 and run it again, we'll see it False, it's not in there.
2:39
So we are going to use this principle to make our test more Pythonic.
2:42
So we can make this shorter, less error-prone,
2:45
easier to read and more Pythonic using that idea,
2:48
so what we'll say is "if m is in the set of moves to the North,
2:54
moves to the South, moves to the West or moves to the East", like so,
2:59
we could use a list, we could use a dictionary,
3:02
but set seems like the right things for what we are trying to express here.
3:05
Let's just run it and make sure that this still works.
3:07
So if we move North, it's a direct move,
3:10
if we move South-East that's a diagonal move.
3:12
Let's just try, let's take West, boom, direct move.
3:17
OK, so that's pretty sleek, right?
3:19
So when we have a single variable
3:21
and we want to test it against multiple conditions, use this "in" keyword,
3:25
now this is extremely readable, but in fact,
3:27
it would be a little bit slower, so most of the time,
3:31
a little bit slower in something like this is you know,
3:35
a millisecond here, a millisecond there, nobody cares, it doesn't matter.
3:38
But if this happened to be within a really tight loop,
3:42
we could improve upon this by taking this set we want to test for
3:46
and moving it outside the loop.
3:47
So we could do some kind of refactor and create a variable here
3:50
and call this say a direct_moves, like that;
3:54
where this gets put somewhere outside of our loop
3:59
and then inside of the loop we can test it like this,
4:02
again this should still work, just like before;
4:04
North, yes that's a direct move,
4:07
but sometimes you may want to avoid this for performance reasons.
4:10
Let's just do a quick little test to actually understand
4:13
what the performance implications are.
4:19
So here we are going to do a "for...in loop" one million times
4:22
and let's start out with the version that is not so Pythonic with the multiple tests,
4:28
we'll just compute the boolean over and over and over
4:30
and see how long that took.
4:32
So let's run this.
4:33
So it took 0.2 seconds, so 200 milliseconds for a million moves,
4:38
chances are this doesn't really matter for you,
4:41
but if we want to figure out how long that took for one,
4:43
we could do something like this,
4:45
so 10 to the -7, extremely fast but like I said,
4:50
if you do it in a million times, hey maybe it matters,
4:53
let's test a version that is more Pythonic but slightly slower.
4:57
Here 0.3 instead of 0.2, no big deal,
5:00
however we wanted allocating the set each time to the loop,
5:03
you'll see this is fairly slower.
5:08
So 2 seconds, instead of 0.2 seconds,
5:10
so that's like 10 times slower,
5:12
so you really have to decide how much does this performance matter
5:16
you can see it's almost entirely negligible
5:18
when you extract it outside of the loop, and you write it like this,
5:24
it's still quite fast but it does put indent in when you do it this way.
5:31
So here I commented out a little test if you want to play with it,
5:33
feel free to uncomment it,
5:35
you should really thrive to do this, this sort of test here,
5:37
and maybe I'll make it the most readable version
5:39
until we have a performance problem, so we can inline this here,
5:45
excellent,
5:46
so here is a nice Pythonic way to test a single variable
5:50
against multiple values in Python.
5:53
So this is probably the most natural way to write this code
5:56
coming from somewhere like C++, Java, C# and so on,
5:59
however, in Python we can use this set and the "n" operator
6:04
to make this much readable,
6:06
now if we want to see all the cases,
6:08
it's very easy just look at what's in the set if you want to add or remove one
6:11
easy to do and you won't miss an "or" with an "end"
6:15
or drop a parenthesis or something weird like that.