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