 We have Rodrigo and the talk is going to be based on Python don't write elegant Python code. So he's going to be talking about the subjective notion of beautiful or elegant code. And the talk is based on a series of articles has been publishing on his website. That's pp.com and he is based in Portugal. So hello Rodrigo. Hello. How is everyone doing? Thank you. Very nice to have you today. Okay. Thank you for the invitation. I'm assuming I have the green lights to go. Yes. Okay. Thank you very much. So hello everyone. Welcome. Like Yasmin said, my name is Rodrigo. And today I will be telling you all about the pythons. So how to write elegant Python code. But before that, in order to break the ice, let me tell you just a little bit about myself. So my name is Rodrigo and my formal education is in mathematics. So I have a master's degree in applied mathematics. I have been writing code for 12 years now and Python in particular for nine years. And the way I pay my bills is through training and teaching that I do. I do some APL training for dialogue limited and APL is also a programming language. And then I do some training and teaching of Python and mathematics and all those related topics through, I think we could say through my personal project that you can find on mathspp.com. And by the way, you can, you can connect with me on Twitter at mathspp blog. Well, throughout the talk, I'll be referencing some articles and I will share all of those links afterwards over there. So you can, if you follow there, then you don't need to copy the links now. And also, there's an Easter egg in the slides. So there's something in these slides that might trigger you a little bit if you are very used to writing Python code. And it wasn't intentional. But when I noticed it, I thought, well, I'll leave it there. And so let's see if people can spot it. So if you can spot the Easter egg in those slides, feel free to reach out to me on Twitter and let me know that you found the Easter egg. Now on to the talk itself. So Python's right elegant Python code. Well, what's, what's this? What's the pythons? If you, in case you haven't understood yet, the word pythons is actually a play on the words Python, which is the, well, the name of the programming language we all know and love. And then that common phrase, the do's and don'ts of something. So the do's and don'ts of Python are the pythons. And today I will be trying to show you how you can use these pythons to write elegant Python code. And, well, what's that? What's elegant Python code? Why do I care about that? Well, paraphrasing Dijkstra that you might know because, well, you may know Dijkstra because there's an algorithm with his name. Paraphrasing him elegance is not a dispensable luxury, but a factor that decides between success and failure. And so I want you to understand that in here, when we talk about elegance and when we talk about elegant code, it's not just the as theoretical, the as theoretical feel or the code being aesthetically pleasing. There's actually much more to that. Elegant code for the case of Python, it's code that's readable. It's code that makes the best use of Python's features and that makes use good use of those features so that your code becomes much more expressive, less error prone, easier to debug, etc. And that's why we care about elegant code. In order to show you some of the things that you can do to make your code more elegant and to make your code more expressive and more readable and etc. I have a little story that I want to share with you. But first, and I think I should have said this in the beginning, but you know, this is my first conference talk ever, so I'm a little bit nervous. Feel free to ask any questions. There will be some Q&A time later. So, yeah, ask your questions now and I'll address them the best way I can in the end. Now, on to the story that I want to tell you, the thing that I want to share with you. There's this programming task that a beginner completed. So there's a task that I'm going to describe a problem that I'm going to tell you all about and a beginner wrote some Python code to solve that task. And the code is perfectly fine. It solves the task and it's correct. And what we are going to do during these next minutes during this talk is we are going to look at that code and we are going to refactor it little by little in order to improve it. Every time we change the code, we are going to try and improve it a little bit by using a Python feature or some interesting concept. And by the end of the talk, we will have a piece of code that does the exact same thing, but looks fairly different. And so that is our objective. And by the way, these, these little changes that we are going to make and these Python features that we are going to use and to introduce throughout the talk. Those are really cool features in my opinion. Well, I know I'm biased, but those are really cool Python features and I want to tell you all about them. And like Yasmin said, there's some articles that I've written that I started writing when the year started in order to, to understand how these cool features are used in the real world. So for example, if you take a look at the Python standard library, how are these things used. And the idea is that is to help beginners really understand how to use those things and the rationale for that is really simple. Python has an amazing ecosystem and there's plenty of really cool frameworks that you can just import and start to use, right? And because of that, sometimes people forget to learn like the fundamentals and the basics and they just start using the frameworks. And so when they have to write some actual code, they just don't have the tools. And so that's, that's my objective is to give you the tools to write the best Python code possible. So the task that the beginner is going to solve is to write a function that takes in a string and returns the same string, but with the characters with the casing alternated. So we can see here that we get an uppercase, a lowercase, an uppercase, a lowercase, etc. And that's what I want the function to do. And just to be absolutely clear about the specification of the function. We always try to change the casing of the character, even if the character doesn't have a different casing. So this doesn't make much sense, but this is a lowercase space. This is an uppercase space and this is a lowercase space. So having white space or punctuation or whatever it doesn't matter, we still, we always go up, down, up, down, etc. So this is the task that the beginner had to solve. And this is the code that I was presented with. So if you can take, if you take a look at this, there's a function that's solving this task. We have this empty list that starts out well, empty. And then we go through the arguments and we change the casing of the letter and in the end we join everything. You know, and I looked at this code and this was written by a real, a real person. This is real code written by a real person that is learning Python and I looked at it and I thought, well, this is, I like this. It's fairly easy to understand. There's the formula that's traversing the list and we use the correct method. So there's the upper and lower methods being used there. I think this is a pretty good start, you know, but then I thought, well, what can I make? What can I do to improve this code even if only a little bit? And so I studied the code for a bit and I came up with this alternative solution. It's actually a little bit shorter, but well, that's not what's important here. The thing is that I'm using a couple of interesting features that maybe the beginner, that beginner didn't know about. And so I'm going to tell you all about those features and we are going to do these changes little by little so that going from this to this doesn't look as daunting as it might look in the first place. And so let's start with something about code style. So I faced the beginner and I tell them, well, code style really matters, you know, it's all about finding a consistent style to write your Python code. Because if you write your code in a consistent style, then your brain will have an easier time reading the code. And the same thing for other people. Because if there's one thing that's really to the point is something that Guido van Rossen wrote in the peptide, which is a document that has some code style guidelines. There's a set of guidelines written by Guido and in the pept, Guido said that code is read more often than it is written. And so it's your job as a good programmer to write good code that is easy to read. And so code style goes a long way. How does that apply to the code that we have right now? Well, code style and Python is all about white space. Interestingly enough, the document that I told you about Pepe has lots of interesting guidelines that you are free to follow or not. And plenty of those guidelines are related to white space. So blank lines, spaces around things. And in fact, if you take a look at these two pieces of code that we see here, the assignment and this expression right here, it's a little bit too cluttered. You know, why don't we give it more room to breathe? It's nice if your code can breathe a little. And so this was a very minimal change, but it was our first change, our first small improvement. And now we can just keep going, right? If code style matters, well, certainly naming also matters. And this is incredibly important and it's much more important than some people might think or some beginners might think. And well, why is that? If you think about it, what are names? Names are labels that we use in our brain to attribute a, well, a small word or a smaller sentence to a complex concept or a complex idea or a complex object, right? Those are names. But if you also think about it, or you can also think about it as names being the real estate in our brains. Our brain has a fairly limited capacity to hold different things. And so we use names to make it easier to hold the information in our heads. But this real estate is really expensive. So you have to make the best use possible of the names that you use in your code. And so how does that apply to this code? What can we do to make sure that our names here are the best possible? Well, I don't know if you've ever heard this, but I've read this and I've heard people say this. Naming things is the hardest programming problem that you will ever have to solve. And so there's no way to pick the best name or generally there's no best name. You can just try to make your names better. And we will try to do that. We will try to make these names better. So the first thing we do is we take a look at the names that are being used in this function. And now we think a little bit about what names could I pick that are better than these. And in picking good names, in picking good names for your variables, for your functions, for your classes, for everything. I think there are two major guidelines that you can try to follow. You can pick names that reflect really well what that object or what that thing is or does. Or you can pick, well, and slash or you can pick a name that reflects a major property of that thing, of that object, of that function, etc. And it's really interesting. I was talking to the beginner, to that beginner that wrote the code and I said, well, it's really interesting that you almost did that with this assignment right here. So if you take a look, what's there? There's an empty list. And so you thought, well, this is an empty list. So I'll call it empty, right? It makes sense. And this assignment in and of itself makes a lot of sense. But the problem is two lines down or three lines down, you have a for loop and you are appending things to that list. So that list quickly stops being empty. And so the name isn't the best possible. So yeah, we can take a look at these names and we can try to come up with alternatives. And you know, these were the alternatives I proposed. Let's change the name of the function to alternate casing. Let's change the name of the parameter to text. Now it's a little bit easier to guess what's in there. I, well, this is a personal preference, but I even prefer ID X for index over I when I have, you know, when I have space for that. And well, I called the empty list instead of empty, I called it letters. And now you might even argue well, Rodrigo letters isn't that great of a name either because the text can contain other characters. So maybe we should call these characters instead and you are absolutely right. And to be 100% honest, I only noticed maybe one hour ago that this wasn't the best name that I could come up with characters was perhaps a better name. But this just goes to show that reading your own code and thinking about your own code will inevitably make you better and make you question. Well, what if I did things some other way and that's really important in your journey to become a better programmer. You just have to read your code and see, well, now that I've learned new things, what can I do to improve my code. And now that we've taken care of some code style and some naming, let's actually jump into one of my absolute favorite things about Python. Now, I don't think I can say I'm a master of Python. And to be honest, well, I'm not a master of any programming language, because Python is the one I know best. So if I'm not a master of Python, I can't be a master of any other programming language. But I have fiddled and played around with some other programming languages. And to me, Python's for loops are the best out of every single programming language I've played around with. And why is that? Because Python's for loops, they come up, they come with Python comes with so many interesting functions and build teams to work with the with the for loops that just make them so expressive and so powerful. And what's really cool is that if you if you give good names to your variables, like we just described or like we just talked about, then your for loops, they can be read as almost English sentences. And to me, that's just one of the beauties of Python. So yeah, we have this enumerate me slide over here. This is referring to one of the articles that's written about the enumerate built in. And so let's see what the enumerate built in can do for us. Well, I'm sure everyone can relate to this small task, we have some list that we want to traverse. And then, especially and this is really interesting, especially people that have backgrounds in some other types of programming languages, they might be tempted to write something like this. Let's have an index that's iterating over the range of the length of the list. And then we index into the list to work with that element. And so how does one read this in English? Well, the range of the length of the list is actually an idiom. So this can be read as for each index in the legal indices of my list, just do something with that element. But this is such a common operation that Python allows you to rewrite this as the shorter and more expressive for element in my list. And the way you read this, notice this is one, two, three, four words. Well, in the code and in English, you can read this as for each element in my list, do such and such. Right, so this is much shorter and much more expressive. And this is even better than the previous alternative because there are some things that you can iterate over. And I like to think of iterating over something as going through that sequence or that object or whatever. And some things that can be iterated over cannot be indexed. So this pattern right here applies more often than this pattern. And to me, that's already a huge win. So this is a really cool pattern that you can use in Python if you weren't aware. But well, now you might be wondering or thinking, well, Rodrigo, this is all nice and fine. But you also need the index because your if statement was making use of the index to determine whether to make a character uppercase or lowercase, and you are absolutely right. So the pattern we were dealing with was actually a little bit more complex. It was traversing a list and also keeping track of the indices. Right, that's what we have. And so people then fall back to the previous pattern and they just write something like this. For each index in the legal indices of my list. Well, let's start by grabbing the element and then we can work with it later. Okay, that's fine. I totally understand that you would write this for loop except Python has an amazing built in specifically for this use case. This is so common that Python provides you with the enumerate built in and it just does what it says on the team. It enumerates any terrible and so it allows you to go through the indices and the corresponding elements in a single statement. And so this is read as for each index and corresponding elements in my list. And now you can do the work with the index and the element. And don't even get me started on other functions like zip, which is another amazing function for for loops. So that's a whole a whole new world but unfortunately there's no or fortunately there's no need for that in in our code. So this is the code we have. Remember, now, can we spot the pattern that we have or that we were talking about? Well, yes, we can. There's the for looping here. There's the index and the range of the length of the text and we are using the index and the element. We are using both. And so what you can do is you can replace the range of the length with an enumeration. And now you get a good name for the index and a good name for the character for free because you are iterating over the enumeration. And there you have it, our third little improvement. And at this point, the code has been, well, the shape of the code hasn't changed much yet and that's fine. And we even have a couple of steps or little refactorings that actually made the code larger, but that's perfectly fine. Shorter code doesn't mean better code. Better code is better code. It might be shorter or longer. So if you need to make your code a little bit longer and by doing so better, that's fine. The objective is not to have the shortest amount of code possible. So keep that in mind because some people have a hard time distinguishing this. When they see short code, they think you are trying to be clever when sometimes short code just happens because you're making the best use of the tools you have, right? So if there's a function call that solves everything, well, in one function call, why would you write three, four loops and two while and five ifs? Now, the next concept that I would like to discuss is the concept of nesting sparingly. And in order to do that, I would like to start the discussion by importing this and this is actually Python code. So you can go to the interpreter and type import this and you will be presented with a little text. It's called the Zenf Python, which was written by Tim Peters, someone that had a big influence in Python. And these are, you can think of these as like 19 commandments for Python code. I'm pretty sure it's 19. I hope I'm not making a mistake. But what I would like is to focus on this right here. So flat is better than nested. But you know, don't take me for my word nor even Tim Peters, let's actually some practical use cases where flat is better than nested. And I think one of the quintessential examples of this is a situation like this. There's a try accept. And what we have here is the first function does some pre-processing. It does some things to set up a major operation that you want to do. Then you have your main function that might throw some error because sometimes things fail, you know. And then there's some function that does some post-processing, assuming that your main operation work. And then because you know that the middle function might throw an error, what you do is you have this accept clause right here that's printing a whoopsie and trying to correct the mistake. Because you know, well, if there was an index error, I know exactly what happened and so I can play around that. And this is, this makes sense. This is more or less what the try accept block was created for except pun not intended. But yeah, except that what if the first function or the third function, what if any of those two functions also throw an index error? Maybe because you have a bug in your code or maybe because this is using some third party code code that you can't control and that just throws an index error. Well, if that happens, this except clause is going to be caught. Sorry, this except clause is going to try to handle that error, but you're not supposed to be handling that error. So you're trying to correct a mistake that never happened. And now weird things are stacking on top of each other and who knows where this might might leave to. And so when you have a try accept, you should have the least amount code, the least amount of code possible inside the try. To be absolutely sure that you don't pick up on errors that you didn't want to pick up on. And there's another there's another really good example that comes when you're trying to open a file and read the file and then do something with the contents of the file, right? We in here we are reading the contents of a file and then we are trying to process the contents, except that in order to process the contents. I don't need the file anymore. So I can actually release it so that the file system and that the operating system can do whatever they please with the file. There's no need to keep holding on to that file. And so in here we also unnest the processing of the contents. Now what's common to these two use cases and to the ones that I will that we are going to talk about related to our code. Well, nesting introduces semantic dependencies and therefore the less the better because again, our brains are amazing, but they are surprisingly limited. And so if you have a function which then has an if with a for with a try and then some other code and etc. Suddenly you're six levels deep and you need to remember all of the things that you've read before to make sure you understand the code you're looking at. And well, I guess some people have a greater capability to do that. But in general, that's hard. So if we if we stick to clothes that is as flat as possible, we are introducing less semantic dependencies. And how can you spot those things? How can you know when to unnest things? Well, I've shown you two examples. And there's a third one that in my opinion is the most interesting, but also maybe the hardest. And that's when you have an if statement with an else. And you have a pattern that is repeated on both the if and the else. So there's a pattern. There's some operation. There's something that you're doing either way, regardless of the condition. And in this case, I'm sure you already found the pattern or I'm sure you found the pattern already. That's the appending. I'm appending on both cases. What's changing is what I'm appending. And so I could argue that maybe we could extract this repeated pattern outside of the if so that it's absolutely clear that we always append something. It's what's appended that changes. And now it's even it's faster to find that the difference between the if and the else is in the character that we are working with because there's the assignment right there. And we just added one line to the code. And this goes to show that, you know, maybe trying to improve your code makes you write longer code. And that's fine. And maybe some of you don't agree with this change. That's also fine. What I'm arguing is that if we do this, we are opening up the door for other possible refactorings. And we will see just in a second how this makes it even easier to spot some other really interesting patterns. Now, if we keep going, this is the code we have right now. If we keep going, we can now talk about, again, another feature that I absolutely I cannot tell you how much I like this in Python. It's absolutely amazing. And well, what am I talking about? I'm talking about the truthy and falsely values of things of objects. And what this is, is not only do we have two billion literals, which are true and false, but every other object in Python can also be interpreted as a Boolean when needed. And you can do that explicitly with the bool function, which is a building. So B double O L. So go ahead, open your interpreter. Well, not right now, but later. Open your interpreters and try calling the bull function on whatever object you can think of and see what happens. Well, okay, Rodrigo, I see you're very excited about this, but what does it have to do with our code or how can we use this? Well, let me start by showing you an example. I have a list here and I want to print the last element of the list. Well, but I know that if the list is empty, I cannot index into it. So what I do is I check if the length of the list is greater than zero. If it is, I print the last element and if it's not, I just cry a little bit or I'm sad. And I want you to focus on the condition here. So let's look at the condition now what's happening. What's happening is that the length of the list is actually three. So we are checking if three is greater than zero. Well, it certainly is. And so this evaluates to true. And so this is the statement that is executed. But if you make use of the truthy and falsely value of lists, you can actually take this condition right here. So the condition in the if and you can change it to be if my list. And once again, the fact that you can read Python as English is really important. This is a idiomatic, this is very Pythonic. This is an an idiom. And the way you read this is if my list has contents or if there's some content in my list, this is the way you can read this. You can also read this as if my list is not empty, then do whatever, but I prefer the affirmative version. So if there's some contents in my list, then print the last element. And what's happening under the hood or the mental model for what's happening is that we are calling the bull function on my list. And so depending on whether this returns true or false, we interpret a list as true or false. And in order to be able to, and of course in this case, my list is interpreted as true because it has contents in it. And in order to be able to harness the power of the truth and the falsely values of things, maybe the best or the easiest thing to do is to be aware of the values that are actually falsely, because most things are truthy. So if you know what the falsely things are, you have an easier time knowing what's going to be truthy. And both the zero integer and float are falsely. None is falsely. And then you see here the empty string, empty list, empty dictionary, empty tuple, then empty set. These show you that in general empty sequences, empty containers are falsely and then all other sequences and containers are truthy. So how do you use this in your code? Just imagine when you have an if statement and you have a condition, you don't do if condition equals equals true, right? The comparison to true is superfluous. You don't need it. And so in some cases you can see that comparing to falsely is also superfluous. You don't need to compare to a falsely thing. You can just use the falsely value or the truthy value of the expression. And so if we look at the if statement that we have right here, we are comparing the index module two. We are comparing it with falsely because zero is the falsely value for integers. And so what we can do is we can take a look at the whole if statement, so the if, the else and the two expressions inside or the two assignment statements. And we can think about what would happen if we were to remove this comparison. Now if we remove this comparison, because this is comparing to falsely, in order to stay to keep the same logical reasoning, we either insert a knot here or we flip these two statements. And I think that we can actually flip the two statements. It's perfectly fine. And then we get yet another idiomatic expression. The way you can read something like this is if index does not divide evenly into two, then do such and such, otherwise, etc. And in particular, because there's a two here, the way this reads is if index is odd, do this, otherwise do that. And there you have it. This is our piece of code right now. Now circling back to when I told you about nesting sparingly and when we extracted these letters dot append, I told you that writing code like this would open up the doors for something that I think is also great. And that thing that I think is also great is conditional expressions. And conditional expressions, they just do what it says on the team. They are expressions that your value weights to two different values depending on a condition. And that's exactly what we need right here, because if you take a look at our if statements, what you see is that when we extracted this pattern that was happening on both the if and the else, we inserted something else that is also happening on both cases, which is the assignment. So we are assigning, we are always assigning what's different is what gets assigned. And this is such a common thing to happen. This is such a common construct that there's a shorter way to write this and a more expressive way to write this. And well, that's called the conditional expression and it looks like this. You say that capitalized is the lowercase version of the character if index is off. Otherwise, it's the uppercase version and then, well, you append. But yet again, let's circle back to when we talked about how naming matters. And we are using a name here. We are spending a name. We are spending a label. We are allocating some space to something, but we don't need it later. So there's no need for this name. So we can just get rid of it. And then this is what the code looks like at this point and all of a sudden through the use of one single feature, it looks like it was only through the use of one single feature, but all these changes on top of each other allowed you to make your code significantly shorter and at the same time, much more expressive. And to me, just take a moment, just take a look at this code. I think this is absolutely beautiful and we are not done yet. But at this point, you should be really proud of yourself if you were able to reflect your code up to this point. I think this already shows an amazing mastery of some of the most interesting Python core features. Now onto another feature that I'm a huge fan of and that's list comprehensions. And in my opinion, list comprehensions are great for a variety of reasons. And one of them being that with list comprehensions, what you can do is, and then by the way, this generalizes to dictionary comprehensions and generator expressions and etc. So knowing list comprehensions really opens up a lot of doors, but list comprehensions specifically, they allow you to define a list and at the same time fill it in with the values that you know the list needs. So there's this very common pattern of initializing a list to be the empty list and then you write a for loop that goes over some iterable and you take the list and you append the element of that iterable after processing it with some function. This is a very, very common pattern. But the fact is, these three lines of code, they are so simple. If you look at it and if you think about it, there's nothing inherently amazing or extraordinary happening here. This is a very, very simple pattern. It's the pattern of populating a list with a bunch of elements. And this is so common and this is such a common operation that Python has a way to write this in a more expressive way. So to make it clearer that we are initializing a list with such and such elements processed in some way. And the way you do that with the list comprehension is you shuffle things around a little bit and you just write this. And now you have your list that starts to be the, it's the list that contains the elements after being processed, you know, and just take the elements from the iterable. So process the element for each element in your iterable and this is a list comprehension. And again, I just think that this is absolutely beautiful to be, well, to be completely honest with you. Now, how does that apply to our code? Well, it's just a matter of looking for the pattern. Can you see the pattern? Well, yes, you can. There's an empty list there. It was even called empty in the beginning, but well, no longer. There's an empty list. There's a for loop. And then there's the append operation letters that appends. And now we can think of this conditional expression that picks either the lowercase version or the uppercase version. This is the funk from before this is the processing that is happening. And so what we do is we take this and we shuffle things around and write a list comprehension. And now we don't want huge lines because huge lines are difficult to read. So we just take the liberty of breaking the least comprehension right before the four. So you have the processing of the elements and then where the elements are drawn from. And so this is the piece of code that you have. And now once more, circling back to the fact that naming matters, we are initializing a list of letters that we have actually discussed that should be maybe called characters because this doesn't only have letters in it. It can contain punctuation or other characters. So you have this list. And now in order to return the final string, you need to join everything. And then this name is no longer used. It's used nowhere else. And so why spend brainpower if you don't need to spend that brainpower. And there you have it. This is the final piece of code that I presented as the alternative solution. Now take a look at this. Try to remember what we started with. We started with a larger function that had a for loop. It was iterating over the range of the length of the least we have an if statements we have lots of things happening and then we took a look at how co style matters we took a look at how naming matters. We took a look at Python's enumerate built in we took a look at how people or how we should or shouldn't nest our code. We also took a look at conditional expressions truthy and falsely values, and even least comprehensions. And through the use of these concepts and ideas and buildings we were able to rewrite our function to be this. Now, some of the steps here were or are actually covered in some of some of these articles like I said in the beginning of the year. We started out on a journey to find the best use cases the the the most idiomatic use cases for all of the Python features so these are some of the articles that influence this talk. And well if you want you can also find all of these articles compiled into a new book that you can get at gun dot co slash pythons. And yeah, again, remember that there was an Easter egg. In the slide so if you find that Easter egg, feel free to find me on Twitter at math pp blog, and also I'll tweet all of the so the references and all of the links that are relevant I'll post them there so that you have an easier time finding everything. And I also think some people might be interested in all the stuff that I teach and all the articles that I write so you can find my newsletter at maths pp.com slash subscribe if you're the type of person. And then the talks the talks the slides for this talk you can find them on github at github.com well obviously slash math pp slash talks. I will be taking any questions you might have and I, I welcome you to actually writes to me because I love connecting with people. So if you have any comments or any questions any feedback. I would appreciate if you reach out to me on or at Rodrigo at math pp.com so thank you very much for being there. And I look forward to your questions. Thank you very much for your talk. So there's a few questions. If you don't mind. And so the first question that people had is, what did you use for these and nice animations of the code listings. Okay, so this is, I don't judge you if you're asking this I've asked this myself lots of times so I just used PowerPoints. The 19 version so from 2019 and then it's a slight transition called morph. And you just have to set it so that it morphs on characters on words and it just shuffle things around and it's, it's really sleek so thank you for noticing it was a lot of hard work to get that to work. So, and then the next question that was asked is, in the code for the truthy fall see for getting the last element, I wouldn't try except be more pythonic. Yes. So that's actually, yeah, that's an excellent question. Yeah. So there's this. Well, I don't think there's a clear yes or no answer. I can totally see where this question is coming from because there's this thing in Python that's called the it's easier to ask for forgiveness than permission. And so what that what that means is that in general if you have a piece of code that you know will fail only a small amount of times you can actually do a try and then just run the code that you want to run and then in the case that it falls you haven't accept and that's more pythonic in general than having an if else. So this is actually an excellent question. But it's I think it's a matter of taste and I just think it looked cleaner and simpler for that particular example, because the focus was on the condition so I wanted to be able to talk about the conditions. And the simplest example I could come up with was the well accessing some element of the list. Thank you for your questions. I think it was a great question. Yes. Yes, I think the person that asked they had mentioned the EFP like easier to ask for that issue is also what I forgot to mention. And then the next thing is at the Easter egg I think was spotted by our viewers so if you don't mind being revealed. I think it's okay. Yeah, let's see. Yeah, so was it this. No, that's I see yeah so the capitalization of a letter doesn't necessarily mean that it's uppercase if I'm not mistaken. The letter that's so the capitalization is the letter being upper or lower case that was not the Easter egg. It was not that assignment. It's something else that's a good attempt. And then because everyone is saying it was a really great talk and also they were saying that it's really helpful to look at several times is your presentation available. Yes, so the slides. First and foremost, all of so the whole talk was inspired or essentially drawn out from the pythons that I writes weekly on my blog. So just you can Google for pythons and hopefully you can find my blog and you can find all of the concepts explained there. The slides themselves will be published online on GitHub slash maths pp slash talks. But like I said, all of the links, I will send them to my Twitter so that everyone can access them easily so it's just at maths pp blog and everything will be there. So yeah, thank you. Thank you very much for your feedback. Thank you very much for your talk today and for your presentation. Thank you for the invitation.