 Thank you So Let's see what I can talk about. Well, first of all a bit about myself. I don't know if you know me. I'm Mark Limburg I'm I've been doing Python for quite a long time. I started very early I have a company doing a Python project for customers. I'm a senior architect for Python and Do consulting training. I'm also a Python core developer. I am board member of the PSF and board member of the EPS and I'm based in the door from Germany so I Thought I'd put together a talk with some Python idioms that might be useful for you This talk is basically focused on on people that have just started programming Python and have all these nice things These nice tools out there and nice ways of doing things in Python, but sometimes don't really know which of the Possibilities there are they should use in their code and maybe want to get some guidance in in writing better code So unfortunately, this is the only photograph I have in the slides. Most of the other stuff is just text There's lots of text on the slides. I'm not going to read everything for you. You don't have to read everything I'm going to put the slides up Afterwards and then you can download it if you don't want to get more information from it So this is the agenda Quite a few bullets there. So let's start so I can finish on time. So first thing coding conventions, of course you want to know how to actually write the your code and Fortunately in in Python, we have a standard for this. It's the pep8 standard You can download it on the on the Python.org website It has evolved a lot over the very over the years. It's constantly being updated To address new questions that you might have It's written in a way that allows you to write readable code That's one of the I think one of the best features in Python that you have that you it's very easy to write readable code It's a guideline. It's not necessarily Fixed in any way. You can you can change things in there if you want to you can build your corporate coding guidelines based on it there's some help from a Package called pep8 that you can run to actually check your code against these pep8 Guidelines and then it'll point out various things that you've done wrong. You might want to change them So that's one thing that you should definitely have a look at one thing That's not mentioned in that pep8 is the typical layout of a Python module And I've seen really Well, not very well structured code in in Python modules being written by programmers So the the standard module layout that we usually use in the standard library, for example, or we use in our code that we write It's this one is very basic. You have a header you have a Tool section and then you have a body section and just going to go through this very quickly It always starts with a doc string So you put the documentation for your for your module what's it what the module does on a very high level into the Doc string and you start with the imports I usually put the Python imports first and then the third-party imports as Second list and then I have the application modules as third list So it's very easy to see where various things come from in your code Then the next section is constants I always put them into one section at the top so I can immediately see them and then I have globals Sometimes at least that I need in the module and put them behind the constant so that you can immediately find them if you need them next section then Is the tool section? This is basically used for things that you Mostly only need in your module like there's one exception here, which is the exceptions section Because sometimes these exceptions of course they wander outside your your module And then you want to be able to to see where they're coming from So first you define all the the exceptions that you have in your module and then you define the helper functions Defining exceptions by the way, it's very easy You can just subclass the the ones that you have in in Python and then you can have specific exceptions for your module Which is helpful Especially when debugging because you immediately know where where your which module your exception is coming from then in the body Section, which is basically the meat of the module You first define the functions and then you find define the classes and at the very end You always have this typical if name equals main and execute some main function for example The module execution part. This is run when you import the module and It's only run because you you have this condition here It's only run when you import the module at The the main scope so when you run when you write Python and then module dot part dot py then this part is run You should normally try to avoid having executable code at module scope level so that you don't have any side effects when importing it Sometimes that's not possible, but you should try to do that. So this is the overview The red parts here are basically defining your module API and That's how you can structure your modules if you want to have really clear kind of Approach it then of course, it's like everything in Python. You should always use descriptive names for your modules It should be more or less immediately obvious what the module does There's a typical way of doing that in Python You usually take the most important class for example that you define in the module and you name the the module after that class I already told you about the executable code and one recommendation. I have for you You should always use absolute imports if you have packages then you you can also use relative imports But if you have larger projects then absolute imports make your life a lot easier. So you should just avoid the relative imports So now I'm going to start a tour from high level to low level Python idioms. It's basically this is just a collection of things I Put together. I don't have enough time to go into all the various details I could probably talk for a few hours mentioning everything So I'm just gonna skim a few things. I'm gonna give you pointers for other things that you can look at The first thing I want to start with is common patterns that you have in Python How many of you know coding patterns like the Gamma book for example? Not that many people so software patterns are basically things that that people have become aware of common things that you You do again and again when programming things So there was the the gang of four. I don't know how many years ago many years ago anyway They wrote a book called the The Gamma book and that Basically lists a lot of current patterns that you find in software design And and these are just these are some patterns that you have in Python some of them are not not mentioned in that Gamma book The most famous pattern in Python, of course, is the duck typing pattern. So in Python everything happens using Using duck typing you're always interested in your API. You're not so much interested in which base class This some object is derived from so The the principle behind duck typing is if it if it looks like a duck if it's Quarks like a duck then it's probably a duck and that's good enough for Python So it's not like in Java or statically typed languages We actually have to make sure that a certain base class is being used and there are lots of like examples of that in the Python standard library The next one is the facade or the adapter pattern. This is Used in conjunction with the duck typing pattern You try to make an object that you have look like in a other object So basically you make some for example some bird make Make a bird look like a duck so that you can use it in your code that uses the duck interface This is the facade or the adapter code And again, there are many examples of that in Python then we have singletons. You probably know false and true None is also a single thing ellipsis is a single thing. We have a special single encode not implemented You probably don't know that the small integers in CPython are singletons. So there only exist ones in your process The next one is factories. So in Python You only have a single in it thunder in it method to create objects from classes and sometimes you want different ways of creating your objects and Before we had static Sorry before we had class methods in in Python. The only way to do that was Defining a function and just a regular function which then returned a an instance of that class and Nowadays, this is not recommended anymore nowadays. You should use class methods for this So this is just a way of having multiple in it methods basically multiple ways of Defining your or initializing your objects The next pattern is wrappers or proxies. This is again similar to the facade or adapter in these cases you try to hide certain things from other objects or you try to Add certain information to objects. It's very commonly used in for example in decorators When doing this in decorators, you should watch out that you don't create too many wrappers because then your tracebacks look very ugly You can see that for example if you're using Django and you have a bug in your in your Django code You sometimes get tracebacks that span multiple pages, which is not very nice And most of those the the listings that you have in there are because of these wrappers and they don't really interest you So you should not really Will wrap stuff if you don't really have to And finally we have callbacks callback pattern is a very standard pattern that you use an asynchronous processing for example You can also use it in synchronous processing for example when writing parses so in general whenever some event occurs you register a Handler for that event and that handler is called a callback and And this callback is then called whenever this event happens So for example if a parser hits a certain element type then a certain method is called and you can do something and What's very popular in Python because it's all dynamic you can dynamically also introspect your classes for these handlers so you can dynamically create Handlers that interact with your with your parsing This is very difficult to do in other languages Then finally there is something I want to Put some emphasis on this is not really a coding pattern. It's a code evolution pattern It's the way that you start writing Python code So what you typically do is you have a just a simple script just a few statements that you put into a dot py file and you execute them Then you find that you need to make it more more a bit more complex. Maybe maybe add more features Make it look a little nicer Then you take the sections that you have in there you turn them into functions So the functions is the next kind of evolution if an additional step that you have in your script Then you group the functions and then you can make use of the feature that of the object Oriented features that we have in Python that you can put everything into classes and you reflect to your functions that you've just Created and put them as methods into classes and then you can instantiate your classes You can run your application like that. You can make it Even more feature rich you can add more customizations And once you do that you can start doing subclassing to for example, adapt certain features have Multiple features be more or less the same except for maybe one or two certain details You don't have to repeat yourself all the time and then you can put everything together in loosely coupled components which are basically sets of classes and Tie your whole application together like that and grow really big applications like that I have a complete separate talk about this I'm not going to go in going to go into details here But I just want to recommend when you start writing code don't necessarily start with writing code Just with with classes for example start easy and then get more complex and have your code evolve like that It's much it's a much better way to to evolve your code because then you learn about what you actually need in the code and It's not so much about just Putting everything into into classes and making everything complicated right from the start So next thing performance idioms Again, I have a complete separate talk for this one So I'm just going to mention a few things that are interesting One thing is looping over sequences. You always have to do that in Python code There are various methods of doing that one is the for loop then you have the map function You have list comprehensions and you have generators and I sat down and timed everything and I found that The simple answer is useless comprehensions all the time. It's the fastest way of doing this So if you remember anything from this talk, this is this is a good one to remember Then the next one is joining strings The obvious way of joining strings is just using the plus so the con cat con con cat operator on strings This is good when just having a few strings and it's good for readability because it's it's nice to read The other way of doing this is using the join method on strings So you pass in as parameter a list or any iterable basically the argument the Object that you're iterating you're calling the join method on is the separator that you want to put into your list and Then it'll do the joining for you And this is great for if you have multiple if you have many many strings and all the other methods of doing this That are floating around a mailing list and use groups are not really better than any of these two They're usually slower. They look ugly and you should try to avoid them Something else exceptions if you write code that uses exceptions a lot You should be careful that you write the code and structure the code in a way that you Put the code that runs more often or is more likely to run often into your try it between the try and accept so The if you put code that runs very often or more often than the common case into the exception Part of that try accept then you will find that you'll have a huge slowdown in your in your code This is because it's very expensive to raise Python exceptions. It's not expensive to do that at sea level but if you do it and in Python it's it's Expensive and so you should only use the exceptions for exceptional cases If you do this get this wrong you can have a slowdown of 10 times sometimes because of this So that's why I'm mentioning this and then if you have want to have more of these kinds of performance hints Then please have a look at the swirky page or you can download another talk I gave when performance matters which has a lot more of these details So let's have a look at some coding idioms Something that I sometimes See and in other code in third-party code and I that I look at or code from from other Program as I work with is that they start to nest if statements very deeply and You get this kind of Syndrome what I call a staircase syndrome So your if statements they move tend to move to the to the right all the time And that's a very very simple way of avoiding this this of course this this doesn't look good It's hard to read because you cannot really follow the indention anymore indentation anymore Unfortunately, you have to continue statement in Python which makes it very easy to avoid this whole thing So you just restructure your code a bit and then you just continue to Just switch to the next loop in your for statement And so you don't need the indentation anymore You can just avoid it and everything becomes much more readable The same is also possible with functions except in functions You would use the return statement and not the continue statement Right the next thing to watch out for is mutability or immutability Because in Python everything is or pretty much everything is mutable You can use mutable things in places where it's not a good idea to actually Do so for example if you put mutable things into the module scope for example a database connection then This may look very natural to you This may look nice from from a writing perspective, but it's not thread safe So if you have multiple threads running accessing that same connection It's not it will definitely give you problems sooner later in your application And especially if you use larger applications or you write larger projects, then you should not do this Instead what you can do is you can have context objects and you create these objects They have all the contacts as needed for for example for a web request or an RPC request You put the information in there and you pass around that object and that object would then for example in the database case Would then also have the database connection and you pass it around as first parameter of your functions Or you if you use some classes you put it into a class instance Attribute and do it like that and then you don't you avoid these issues and everything Keeps working the same thing can happen when you define default parameters in functions So for example down here you have func and then a equals none What you what you'd really want for that default parameter is you want a to be an empty list when it's not being passed in as parameter Now if you if you'd use an empty list instead of the none here And then your function starts doing something with with the a parameter here it would The the changes that you make to that list would persist and so all the future function calls to to f To the function funk Would then see those changes that you've made and of course you don't want that So the best way to avoid this is if you have to put something mutable as default parameter Replace it with none and then in your function Use the the mutable parameter that you need as default and put it into your variable inside the function A similar case is for class default attributes So if you have a define a class you have attributes you want to say for example might maybe files It should be supposed to be a list of something Then you'd normally write files equals an empty list you have the same problem again Some method in your in your class may change this list For example in some method and then the change would be on the class object And so all your instances would see those changes and you don't want that so what you do is you you place the Assignment for that instance attribute into your init method to avoid this so Some gotchas How many of you know the in operator in python? All hands that go up really Yeah, so I mean the in operator is used for membership testing So if you want to check whether something is in a list you should definitely use the in operator You should not use the index method that you have on the list This may be a bit unusual for you if you come from coming from other languages Which always use methods for for doing these things It's better to do it that way the for dictionaries is not necessarily obvious What x in some dick would mean in python it means that x the key is in your dictionary So if you test for this because it's the same as the dot has key method and Has keys is deprecated anyway, so you should only use this one for sets Sets were added very late in the language So sets don't even have a method to do this in operation. So you always have to use this which is good So you cannot make any mistakes and Some more gatchas if you do bullying testing in pyson then you have of course you have true and false to Singles I mentioned there are various ways of testing for for boolean for truth of false One way I often see is people writing if x equals true It's not not a good way to do this because it may fail true actually is an integer and it has the value 1 So if you if x for example is is 2 and it's still true, but this won't work so Your print same as print statement wouldn't execute and even more so if you write x If x is true because is actually checks the address of the object and of course Unless x is actually your true single thing this will never be true and never print x is true and Likewise for the not case. So this is something to remember and similarly If you do empty container Testing so you want to check whether a list for example is empty or tupless empty You should always use if and then container because empty containers in Python are always false and Containers that have something are always true So this is much more efficient to do it that way. You don't need the length Function for this you don't need to check with the length is positive because length can only be zero or positive So that's a really not necessary and finally Something I well it's a mistake I often make it's it's the calmer in in Python If you look you have one tuples in Python So you can have a tuple with one element in it and the way to write it is you use the Use the parentheses around the one and you have to have this comma at the end now This is very it's obvious to see that this is a tuple But the next line is also one tuple and this is not obvious to see and the mistake I sometimes make is I add Accidentally add the comma to the end of the line Or maybe I do a copy paste from somewhere and then it the the comma just gets added and as you can see in the example here I Originally wanted to have s equals ABC the string ABC But what happens is it actually creates a one tuple so the length of s is one It's not three as I would have expected and similarly if I index into s I don't get the the C if I ask for s2 I Get an index error because it's a one tuple and it doesn't have a A third element in that index so this is something to watch out for But commas are also nice in Python because you can Python the Python parser is very Very nicely because it allows having commas in places where you normally don't need them and where other languages for example give you an an error message So if you have listings With say a dictionary with items you can have the comma at the end of each Item including the last one that you have in your definition and this is very nice because if you want to add new Elements to that listing you can very easily do so and you just append and a comma and and you're done You don't have to worry about any syntax errors that you might get if the comma is missing And this even works for functions So if you have functions that take a lot of lot lots and lots of parameters you can do it that way as well so I'm just going to show a few more tools That you can use Nice thing in Python is that Whenever someone has a problem they write a tool for it and I put it on pi pi and everyone can use it So we don't have to repeat ourselves all the time There's a very good tool called pylint. This is for style and typo checking had has good documentation It creates quite a few false positives, but you can can you can configure it to not do So you should definitely have a look at that pep 8 already mentioned py flakes is another one It does logical checking Unfortunately, it doesn't have much documentation. So you should probably have a look at flake 8, which is kind of the the combination of tap 8 and flakes and Also as an extra complexity checker it has good documentation So you should probably look at this one and then there is pie checker, which is a very old tool It predates all the other tools. It's not maintained anymore, but it can still give you some good results So now is question time That was it hi Hi What what idiom would you recommend to check if it is not none like I just Need to do some actions if the object is none, but I should not like true Look for true false I Did not really understand your question. We your object is done Ah, none. Yeah, because none is a single and you should always use if x is none as check It's the fastest way of doing it because in C. It's just a pointer comparison And it also immediately becomes clear that you're looking for exactly that particular value So you should not write if x equals none Especially not in Python 3 because that's always gonna fail in except if x is none More questions, no