We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback
00:00

Formal Metadata

Title
Pydon'ts
Title of Series
Number of Parts
115
Author
Contributors
License
CC Attribution - NonCommercial - ShareAlike 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
In this talk I show what idiomatic Python code looks like and illustrate how the subjective notion of “beautiful”, or “elegant” code, can make your code objectively better, regardless of your Python skill level. We do that by visiting several vanilla Python features that people sometimes forget to learn, as they rush to importing all the shiny modules and frameworks they really want to use. In order to achieve this, we go through the learning journey of a hypothetical Pythonista, taking a function written by them and refactoring it incrementally through the use of Pythonic idioms and patterns. The whole talk will build around a weekly series of articles I have been publishing (at https://mathspp.com/blog/pydonts), where I explore all the vanilla Python features that make Python one of the most interesting programming languages to learn. There are no prerequisites for this talk, and both advanced users and beginners can benefit from it.
19
Thumbnail
43:26
CodeSeries (mathematics)Computer virusWritingLink (knot theory)InformationTwitterBlogChannel capacityMathematicsObject-oriented programmingProjective planeRight angleWordFunctional programmingCASE <Informatik>BitVariable (mathematics)Slide ruleDisk read-and-write headComputer programmingSocial classMultiplication signGoodness of fitElectronic mailing listError messageSystem callAlgorithmCategory of beingDivisorTask (computing)Loop (music)Line (geometry)Process (computing)Pauli exclusion principleSet (mathematics)Point (geometry)SpacetimeProgrammer (hardware)ExpressionWave packetComplex (psychology)Degree (graph theory)Exception handlingElement (mathematics)Computer fileSubject indexingPattern languageContent (media)Price indexCorrespondence (mathematics)Statement (computer science)ProgrammschleifeSubsetCore dumpCondition numberRange (statistics)Moment (mathematics)LengthReading (process)Block (periodic table)Operator (mathematics)Game controllerSoftware bugExterior algebraTrailConditional probabilityEnumerated typePairwise comparisonProgrammierstilTupleOperating systemDifferent (Kate Ryan album)File systemProgramming languageFeedbackCode refactoringFreewareKnotCircleAbsolute valueDoubling the cubeString (computer science)Shape (magazine)Boolean algebraBookmark (World Wide Web)Power (physics)Easter egg <Programm>Single-precision floating-point formatInterpreter (computing)Installable File SystemType theoryLetterpress printingRevision controlNP-hardIntegerFocus (optics)Data dictionaryDampingSequenceFile viewer1 (number)Coma BerenicesOrder (biology)Dijkstra's algorithmE-bookVariety (linguistics)NewsletterAutomatic differentiationSoftware frameworkGroup actionPresentation of a groupMorphingLibrary (computing)Fundamental theorem of algebraLatent heatParameter (computer programming)Endliche ModelltheorieMeeting/Interview
Dijkstra's algorithmSlide ruleBitWritingDensity of statesWordCASE <Informatik>Programming languageDivisorEaster egg <Programm>AlgorithmError messageProgrammierstilTask (computing)Computer programmingFreewareMultilaterationMultiplication signComplete metric spaceCodeOrder (biology)Fundamental theorem of algebraStandard deviationObject-oriented programmingMathematicsRight angleFunctional programmingSoftware frameworkString (computer science)Latent heatExpressionExterior algebraSpacetimeParameter (computer programming)Loop (music)Electronic mailing listProcess (computing)Set (mathematics)Programmer (hardware)Point (geometry)Wave packetDegree (graph theory)TwitterProjective planeLink (knot theory)BlogComputer animation
Object-oriented programmingTask (computing)BitCodeElectronic mailing listMultiplication signLengthComputer programmingType theoryRange (statistics)Subject indexingPattern languageStatement (computer science)Reading (process)Price indexTrailOperator (mathematics)Element (mathematics)WordChannel capacityInformationComplex (psychology)Exterior algebraCASE <Informatik>Right angleCorrespondence (mathematics)Line (geometry)System callFunctional programmingDisk read-and-write headCategory of beingProgrammschleifeMathematicsLoop (music)Programming languageProgrammierstilProgrammer (hardware)Parameter (computer programming)Enumerated typeAbsolute valueFreewareBookmark (World Wide Web)Single-precision floating-point formatShape (magazine)Code refactoringComputer animation
Boolean algebraDoubling the cubeContent (media)Electronic mailing listRevision controlObject-oriented programmingFunctional programmingSubject indexingInterpreter (computing)Exception handlingBlock (periodic table)System callProgrammschleifeCASE <Informatik>Type theoryError messageGame controllerSoftware bugPairwise comparisonDampingIntegerOperator (mathematics)Multiplication signOrder (biology)Computer fileCodeSet (mathematics)Open setProcess (computing)Element (mathematics)Statement (computer science)BitLengthExpressionCondition numberPattern language1 (number)Endliche ModelltheorieFile systemMathematicsDifferent (Kate Ryan album)TupleRight angleOperating systemReading (process)Code refactoringLine (geometry)XML
Regulärer Ausdruck <Textverarbeitung>Data modelPoint (geometry)Order (biology)Element (mathematics)Multiplication signCodePattern languageSpacetimeMathematicsProcess (computing)Revision controlCircleRight angleNewsletterFunctional programmingLine (geometry)Electronic mailing listType theoryLengthEnumerated typeSlide ruleRange (statistics)Hand fanCore dumpOperator (mathematics)BitData dictionaryVariety (linguistics)Loop (music)IterationSubject indexingPairwise comparisonExpressionStatement (computer science)E-bookCASE <Informatik>Condition numberTwitterEaster egg <Programm>Link (knot theory)Conditional probabilityProgrammierstilComputer animation
Presentation of a groupCASE <Informatik>Electronic mailing listMorphingNP-hardFile viewerMathematicsElement (mathematics)TwitterCodePresentation of a groupException handlingSlide ruleCondition numberMultiplication signFocus (optics)BlogFeedbackGroup actionLecture/ConferenceComputer animationMeeting/Interview
Transcript: English(auto-generated)
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, matzpp.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 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 to reach out to me on Twitter and let me know that you found the Easter egg. Now onto the talk itself. So pythons write 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 name of the programming language we all know and love. And then that common phrase, the dos and don'ts of something. So the dos 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 Dykstra that you might know because, well, you may know Dykstra 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 aesthetical, the aesthetical 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. And 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 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 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 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 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, et cetera. 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, et cetera.
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 for loop that's traversing the list and we use the correct methods. 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's 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 face 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 Rossum wrote in the peptides, which is a document that has some code style guidelines. There's a set of guidelines written by Guido.
And in the peptides, 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 peptides 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 assignments 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 that 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 either pick names that reflects 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, et cetera. 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.
Well, this is a personal preference, but I even prefer IDX for index over I 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 built-ins to work with the for loops that just make them so expressive and so powerful. And what's really cool is that 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 a medium. 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.
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 redis 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 new world, but unfortunately there's no need for that 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 loop in 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 whiles 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 Zen of Python, which was written by Tim Peters, someone that had a big influence in Python.
And 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 except. 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 works. And then because you know that the middle function might throw an error, what you do is you have this except 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 except 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 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 happens. And now weird things are stacking on top of each other and who knows where this might lead to. And so when you have a try except, you should have 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 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? 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 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 un-nest the processing of the contents.
Now, what's common to these two use cases and to the ones 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 stick to a code 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 un-nest 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 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 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. Well, what am I talking about? I'm talking about the truthy and falsy values of things, of objects.
And what this is is not only do we have two boolean 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 built-in.
So B double O L. So go ahead, open your interpreter. Well, not right now, but later. Open your interpreters and try calling the bool function on whatever object you can think of and see what happens. Well, OK, 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, 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 falsy 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 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 bool 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 truthy and the falsy values of things, maybe the best or the easiest thing to do is to be aware of the values that are actually falsy because most things are truthy. So if you know what the falsy things are, you have an easier time knowing what's going to be truthy.
And both the zero integer and float are falsy. None is falsy and then you see here the empty string, empty list, empty dictionary, empty tuple and empty set. These show you that in general, empty sequences, empty containers are falsy 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 falsy is also superfluous.
You don't need to compare to a falsy thing. You can just use the falsy value or the truthy value of the expression. So if we look at the if statement that we have right here, we are comparing the index module to, we are comparing it with falsy because zero is the falsy 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 will happen if we were to remove this comparison. Now if we remove this comparison, because this is comparing to falsy, in order to stay, to
keep the same logical reasoning, we either insert a not 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, et cetera. And in particular, because there's a two here, the way this reads is if index is off, 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.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 evaluate 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 piece of, 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 assignments. Right? 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 capitalize 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 then 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, on to 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 et cetera. 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 the 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 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.appends. And now we can think of this conditional expression that picks either the lowercase version or the uppercase version. This is the func 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 list comprehension right before the for. 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 list. We have an if statement.
We have lots of things happening. And then we took a look at how code 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 falsy values.
And even list comprehensions. And through the use of these concepts and ideas and built-ins, we were able to rewrite our function to be this. Now, some of the steps here were or are actually covered in some of these articles. Like I said in the beginning of the year,
I set out on a journey to find the best use cases, the most idiomatic use cases for all of the Python features. So these are some of the articles that influenced this talk. And well, if you want, you can also find all of these articles compiled into an e-book that you can get at gum.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 Mathsppblog. And also I'll tweet all of 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 mathspp.com slash subscribe if you're that 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 mathspp slash talks. I will be taking any questions you might have. And I welcome you to actually write 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 mathspp.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, I'm going to ask them. So the first question that people had is, what did you use for these 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 really sleek.
So thank you for noticing. It was a lot of hard work to get that to work. Great. So and then the next question that was asked is, in the code for the truthy falsey for getting the last element,
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 means is that in general, if you have a piece of code that you know will file 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 unlikely case that it fails, you have an except. 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 question and I think it was a great question, yes. Yes, I think the person that asked, they had mentioned the EAFP, like easier to ask for that issue as well, so what I forgot to mention.
And then the next thing is the Easter egg, I think was spotted by our viewers. So if you don't mind that being revealed. I think it's okay, yeah, let's see. So was it this? No, that's, I see, yeah. So the capitalization of a letter doesn't necessarily mean that it's upper case, if I'm not mistaken.
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 was 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, so the whole talk was inspired or essentially drawn out from the pythons that I write 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.