 Hi again, I hope you all had a great lunch break Now we have with us Daniel who has a very interesting talk on pattern matching in Python He I guess is streaming from London He has 20 years of professional background in technology with diverse roles like software engineering project leader and a trainer and He loves Python compilers piano and Dungeons and Dragons over to you Daniel Thank you very much. Is my audio working properly? Yes. Okay. Amazing. Thank you. So, thank you everyone and hello from surprisingly sunny London to everyone and What I want to talk about today is what I think is one of the most exciting features in Python coming up Which is structural pattern matching My name is Daniel. I work as a trainer and training engineers at Bloomberg and and something a bit more relevant about me for this talk is that I'm one of the multiple authors of the Pattern matching peps. It's not a single pep. It's a it's a trilogy like George Lucas did Well, at least not a trilogy of trilogies, but it's three peps because it's it's a big feature and an important to describe it well and discuss it well so This is something that's not present in the latest Python release, which is official Python release, which is three nine But if you don't load one of the Python 3.10 betas, it's available if the implementation is ready you can play with it and and Learn about it. So three ten will be available this October And we will include pattern matching. So let's discuss what is pattern matching and it's about Recognizing objects of different shapes and if we look at the At the background of this of these slides, you can see that there are a lot of different shapes in this background and We can recognize it by different aspects of them We could look at which of these shapes are black and which ones are white We can say which ones are circles or which one are crosses or which one are big and we only get this big white X So there are a lot of different things that you can look about into a shape. So And we're doing this not with a string but with full objects. So what makes objects different? So what's the shape of an object is the first thing we're trying to talk about and The shape of an object of a Python object will be related to its type The if it's a sequence how big it is if it's a mapping for example a dictionary What keys are present in an object and if it's any other instance which attributes are present also there So these are all different things that are present inside an object and that you can care about when describing its shape Also, you can check if the Check for a specific object like an exact value like is this object the number three or even a Combination and nesting of this for example is the attribute full of my instance the value exactly the value three so The first impression you get from from this description is that is this is some sort of Boolean expressions That will tell you yes or no given an object To check if it matches a shape or not but pattern matching goes beyond that and that's one of the keys in key insights of this idea of pattern matching and Which is Why are we checking the shape of the objects and when you're called you're checking the shape of a check? It's because you're about to do Something on it that depends on the shape and typically depends on extracting some data that Where the extraction can only be done if the object has a certain shape so for example if you check that The variable X holds a duck object It's probably because you want to do some duck specific operation on top of it And if you're checking for the length of a sequence is because you probably want to extract some Indices from from the sequence before that length if you check for the presence of Key or an attribute in them in a mapping or any general object It's because you are about to access a key or access that attribute so This is the most important thing checking that the notion matches the pattern and Extracting data aren't normally very related operations and they're close to each other in your goal So can we do both of them? Sort of at the same time can we describe so our patterns one to describe not just a shape But how to extract data from that? And and the fun thing is that if we say okay We need to invent something about the composition of check and also assign the different components into variables and Python Before pattern matching already has something like that So if you look at top line packing and Or it's actually sequence unpacking would be the proper name For example, I can say okay given this sequence I want to take the first element into a the last element into C and everything else into be with this description a comma star B comma C and This will disassemble my sequence It will check that it has a list of elements and it will capture the proper elements in the proper variables So pattern matching is cranking up this idea up to 11 and that's what we will do and the first idea of The first point about how we design the symptoms of patterns is following this example over here that Python already has If you look at this, this is not actually building a list This is actually describing how to assemble a list, but it looks very similar to how you can build a list like this one Where you put a as the first element C as the last and all elements of B in the middle so the object decomposition uses the same syntax as the object creation and When we are taking this idea further away, we will be doing more of this use Our patterns will look like object creations But it's important to recognize that our patterns will be used for the opposite operation from creation Which is decomposing the object into its component parts. So An easy way or entity way to to cities is that when you have a pattern this on the left are patterns You have an object on the right and we call the object being match the subject We can say, okay, can this expression on the left? Generate given some values of the variables the value on the right and In some cases, it's truly truly for example This is this this is the same a variable like X can generate anything because anything could be held into X And that's actually the value that will be captured So a pattern like this X comma Y will only generate lists or sequences of two elements And something like this will only generate integral numbers, but never will generate a float So these are the left are patterns that match these corresponding subjects When there's a tick here and don't match when there's a red X So and there are a lot of different patterns that are available that will be available in Python 3.10 and Let me I Have this big table with all the examples and all the definitions I just want to quickly go over the most prominent of these samples So you don't need to read this whole slide. It's there's a lot of information here But essentially you can check for a specific value like these two examples of the top or this middle example It's even pulling out the constant for a module and you're what you're checking is for equality If you use a variable as a pattern This actually always matches but it will capture the value of the subject inside of the variable that you chose and You have a special case for the underscore variable which always matches, but doesn't capture anything So this is like a placeholder and will be useful in some cases that we'll see We can also use like a like a call to a class name to say Okay This object is an instance of this given type because this looks like creating a dark object But in this case is our we are checking if this can be created with this constructor so We can do compositions of these so for example This is a sequence pattern checking that I have a sequence of two elements and the first element matches pattern and the second Matches this one so this will extract the second element into variable a And we can do more complicity scenarios combining the things above You can also use patterns not just on sequences But also mappings like dictionaries or default these or other Python mappings where you check for the presence of certain keys and check for the values to match certain patterns And again, you can do extract nested extraction over there. So There are some patterns that don't look exactly like Python syntax because we need to do things that were slightly different That what Python logic creation can do for example, this vertical bar essentially means Any of the possible options over here this is called an or pattern because it's doing an or between multiple possibilities We have this as To essentially capture whatever is captured on the pattern on the left into a variable at the right So this allows you to give variable names to more complicated things in in patterns like this or expression between a Boolean or a yes on a string and You you can even have a more complicated cases where you use a variable multiple times in in all the different choices So the the syntax is quite powerful and extends a bit what normally Python can do We also can see that we can match on arbitrary objects based on their attributes So this is checking that my object is a duck and the color of the duck should be green this checking that it's a duck the color of the duck should be green and It should have an age attribute and I will capture the value of the age attribute into a so this is actually like doing all these checks and also capturing this this is great in many cases because it's Simplifying a lot of checks that you normally have to do before access is some nested complicated attribute And you can nest nest even objects for example You can say I want the duck and the mother of that duck should be another duck And I want to capture the age of the mother of the duck like that and this does all the checks and pull the attribute out of that So As you can see, there's a lot of flexibility. There's a lot of options It's possible better if we look at some examples, but also before doing that I mentioned what patterns are but I still haven't explained how patterns fit into the language where where can you use pattern and patterns can only be used In in a single place, which is this new match case statement that has been added to the language Which normally looks like this It has a match with a subject and the subject is any Python expression So a value or a variable or a function call or a least comprehension of whatever you want and Then you have multiple of these case blocks each one containing some code and a pattern And an optional data, which I'll explain in a second so You can think of this as a large if and if statement So the goal of this statement is to choose a single block that will get executed only one block One of these blocks at most will be executed Zero is also a possibility For a block to execute the pattern must match the subject And if there's a Boolean condition over here These Boolean conditions are useful when you want to express a more complicated condition that cannot be expressed with the pattern syntax So you can add some extra extra checks over here so if the pattern of under guard matches this code block will be executed and The case blocks are attempted top to bottom. So There might be multiple pattern matching that that would match Patterns that would match the subject, but only the first one that matches will be the one that runs Something also useful is that this guard can use the variables captured by the pattern. So this also tends to simplify how we can write expressions Let's let's look at some examples of all of this in action so Let me show you and Slicer function that we are writing. Let's say that this is a spec that we've been given this works similar to them Essentially the The range function in function the range function in Python Where you have a mandatory stop argument But you can also provide a start and a step on the left and right So if I want to slice the sequence until the stop point I can pass only this argument beside the sequence If I want to an interval and specify the start point I can I can pass two arguments and if I want to specify the start stop and the interval I pass the Three arguments and that's what I should get. This is my specification When you start writing that you say, okay This argument seem to be optional But you cannot do this in Python because you cannot put an optional argument before a mandatory argument So this confuses Python a bit because it doesn't support directly this case and this is a syntax error. So this this doesn't work So, let's see if we can use pattern matching for this So what I want to do is essentially capture whatever arguments I get With these star arcs and match on that to consider all the different cases and possibilities So if I have only a stop value, I return the sequence and the stop value If I have a start and stop I return the sequence slice with the start and stop And if I if my star arcs is these three arguments I return everything in the slice and use you'll notice that this is not just checking that the length of the list is the proper length For each different scenario, but it's also capturing those variables and these variables are being used on the right So this is a good example of how I'm checking the shape and capturing data all at the same time And how that how that works And also have a final case with this magic underscore wildcard that I mentioned before that matches always Where I'm raising an error if all of the cases above fail Remember that cases are checked from top to bottom So this ensures that this is a very general case that always will match But we will only execute this block if none of the cases above happen So if you look at the spec again You will see that this looks really really similar to our spec As was like as Ekel someone said this is like executable set of code So you can see that in this scenario pattern matching allows us to capture our intent as Developers and make very elegant and readable code, which is which is something nice So let's go into another example, which is the famous FISPAS problem. It's a very common child's game and also a very frequently used in bad programming interviews where you want to go over numbers from one to set 100 You say one two three four five, but instead of saying three every time you hit a multiple of three you say the word this Every time you hit a multiple of five you say the word bus and every time you hit a multiple of both You say FISPAS, so you will say one two FIS for bus FIS seven, etc So if we want to call that There are infinite solutions to this problem, but let's look at the one with pattern matching essentially I have different scenarios and each Which scenario to choose depends on whether my number is divisible by three and sorry And whether my number is divisible by five So I'm matching on this pair of Boolean values. So if both are true It means it's divisible by both so I print FISPAS If it's divisible by three I print FIS if it's divisible by five I print bus and otherwise I print the number So I'm again matching on a pair of values is matching on a tuple Which are Booleans in this case and I'm again relying that the cases go from That the matching goes from top to bottom and this is a very common way of using the match statement Where you put more specific cases at the top and more general cases at the bottom So I don't have to worry about this FIS being printed if The number is also multiple of five because that case was covered before so Let's do something more Interesting and more closer to real life. Let's say we're rendering Some template on a website and I'm getting some user information from the service and my template has to print a greeting for the for the user So I have some sort of user ID. I have this API call That gives me some JSON information about the user given the ID Which is this response and I want to Check what of the of the possible responses that this service gives me are available So I can get either an error or I can get the user and also let's say I have a special case Where I want to make a special reading for the user if the if today's is the birthday of that user So, let's say, okay If I get some if my response is a chaser that has some error key inside of this And this only checks that the error keys present It doesn't care if I have another 20 keys, which is very common API said I have a lot of keys that I don't care about I will raise for example this sort of error if I get the user with the name n and the date of birth the and also This is verification. Let's say starting that today is the birthday of a person born on date D Then I will print happy birthday. I will use the name that they capture here So look that the name that they capture here I'm using inside and the day that I capture I'm using in the in the guard over here I'll print happy birthday to user in any other case not know that this third case will match any user much by the second case But the second case will cover the birthday cases So if it's not the birthday, I will fall back into this third case And we'll just print a generic welcome to the user and if I get anything else from the API probably There's a bag in either the API code or my code. So I'm raising an exception and I telling that I get an unexpected response Again, you can we can see that cases go from specific the one on top to general the one on the on the bottom so a very boring use for a Very boring use case and for Button matching is a switch time and a lot of people saying oh Python now has a switch time and yes You can use this as which time and you can check. Okay. Is this Let's say this HTTP status. Is it 200? Is it an invalid user a 403 code a 301 Which needs to be processed read a break But you can also combine them with a more complicated cases So you can say is the code something within 500 and 599 And essentially captioned captioning the code and using a guard and raising its error And if it's something else, I raise an invalid status and and this works and again in this case I could look at this and say Am I getting anything out of as compared to in this with an if and a leave statement? I'm probably not so this case probably Should be rethought as something that may be made simpler But in some cases if you're saying that you could have more complicated logic and the response here the pattern matching is Is a great fit So something else to be careful about is that I'm using literate constants and and this match properly If I use a variable name, let's say I have a constant which is called HTTP okay with the value 200 And I write HTTP okay, this will actually looks like a variable. So it will Always match in that case you still get some sort of syntax error because python realizes that I'm matching the whole variable And I have cases after that which looks a bit funny So it stops me from From doing that but in many cases, especially if your last case is a constant name But constants invariable and variables in python are the same you will actually Capturing the value into the contents, which is probably not what you want Python will try to help you most of the time here, but careful with this so other other use cases if you look at pep 636 there's an example of a simple parser for a um like a command line user interface where you type commands and and and there are parcel So very simple parsers where you pass list of strings and you want to Check commands and arguments can be done with pattern matching And going over complicated data structures if you if you follow this link the the slides will be in line later um If you follow this link, you'll see an example of a red black tree red black trees are a are fancy Balanced three data structure where those are of two possible colors And you need to maintain some invariance We need to check that if the top node is red and the left child is black and and the right node has a nephew that Does something and all of these conditions can be very succinctly and clearly expressed in patterns. So You can see comparison of how much simpler the the algorithm is with pattern matching. So Going over recursive data structures is is great with better matching and um So let's see how um this uh, this allows us to Not just talk about the future, but how this allows us to use uh to think about code in in different ways So we can think of pattern matching as a decomposition approach And python has some other decomposition approaches. For example, if I want to do a library to represent geometric shapes Uh, we can use op and in logic oriented programming I define a base shape class and a lot of subclasses for example a circle subclass that has an area method that knows how to Compute the area for a circle. This is classical op the lines in the bottom But I can instead put the logic outside of my objects And say welcome male my objects will be damn data structure like python data classes or named apples or anything like that Or more complicated option. It doesn't matter. I don't have this area function that shakes checks the shape of my shape Here and if it's a rectangle, it computes area for a rectangle It computes an area for a square or for a circle Or if it doesn't know how to compute area, it raises an exception So in this case, I'm putting the logic for Uh all area computations in the same place which has some benefits and drawbacks and and the the main point the main pain point here is that It allows me to focus on how I want to decompose things You can say that okay, but in op is very easy to add a new shape because I just define A single class and all the logic is inside of here Well in in in the pattern matching approach I have to add the shapes to all of these possible functions that operating shapes And the code is spread all over And and that is true But I can give you a counter argument when I say if I want to add new functionality rather than new shapes New operations in the osc 20 approach you need to spread new methods all about Well here all of the logic is in the in a single place so the emphasis is What do you what do we want to make extensible? Do we want to make it easy to add verbs to to our system or to add nouns to our systems where verbs are methods and nouns are objects So this is the kind of same things as a method dispatch but Focus on extensibility in a different place. So it's an alternative not a substitute for op And this comes from the functional programming paradigm Where it's typical that we have a typical Dam values and smart functions is the way they call it And essentially data structures don't don't have any behavior and the functions have all the logics to handle multiple cases And this works very well when your Data doesn't change as often as the operations that you want to do on the data For example, some sort of data analysis where every time you get new requirements on how to analyze Data existing data that you have In op you can do this kind of same things with the visitor pattern Which is to sort of solve this problem, but it's a bit cumbersome. You have to define a lot of auxiliary methods and auxiliary classes Pattern matching has a more straightforward syntax than the visitor pattern And it also has additional power because the visitor pattern can only split things apart based on their and Based on their class Well pattern matching can check a lot of different things So you could for example, if you have an ellipsis shape you can have a complicated formula for the area of ellipsis but if you If you know that the that the foci of the ellipsis are in the same place Then that's a circle and you can use a circle formula instead So I see some great questions that I will answer and On the wonder app later on because I don't think we'll have time for questions within the talk And So as comparison, how does this compare with the switch statement? and So the check-in is sequential while some switch statements have these computer go-tos that could be that that are typically faster Because it's based on literals I mean a modern python compiler in the future could do some optimizations If all your values are constant but no one is talking about doing that anytime soon And also In a switch you can use constant values, but you need to be careful with semantics the problem I mentioned before So again, it's not a great substitute for a switch statement. You can use it as that. It's not its main goal So if you want to learn more about this, I recommend you to go in over the peps The three peps cover different things 634 is the specification So it's quite hard and technical and is for language implementers 635 is interesting if you are wondering Quite better matching is designed the way it is Or why should I use it? What are good use cases for this? So that's recommended in this case and and if you already love pattern matching and want to just learn how to use it Use it 636 is a tutorial which guides you step by step through all of the syntax And I have some link with some examples over here I would also like to credit The people who made the slice carnival provided this awesome template And all these are public and there are other pictures and photographs Which are just with permission from the creators And thank you very much for attending This is my twitter. It is very easy to reach me over here And this is my email. I'm also trying to answer anything that comes over pattern matching over here But twitter is probably the best way So Again, thank you very much for attending as last point As I mentioned that I work from Bloomberg Bloomberg is hiring You can find this information about positions in this career sling And also we have a sponsor room in the conference systems and you can jump around and there's people I'm around there. So if you want to talk to some engineers, we're around there And And there's also people from HR if you want to talk about recruiting and hiring So you're welcome to come So if you I'm going to jump out now, I think But if you want to If you want to ask any questions, I'll be in the wonder of me outside the October room. So thank you very much Thank you, Danielle