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.

Talk Python's Mastodon Michael Kennedy's Mastodon