Conf42 Python 2021 - Online

Idiomatic Python: Tools and Tips

Video size:

Abstract

Do you write Python Code or Pythonic Code? What is the difference between the two and why pythonic code is better? How we can write a good quality code which is more pythonic?

What tools are available to measure the quality of code and help you in writing pythonic code? Why writing pythonic code is important and what are the helpful tools available to guide programmers? I will try to answer all these questions along with tips, for writting idiomatic python, in this talk.

Summary

  • Amara from Pakistan has been working with Python for more than six years. She will discuss why it is important to write pythonic code and how it relates to the quality of the code. In the end she will share some common pythonic idioms.
  • Any program, function or block of code that follows style guidelines and make use of Python's unique capabilities is said to be pythonic code. Code quality is important because of the following reasons. The third and most important attribute of a good quality code is that it is readable, maintainable and extendable.
  • Zen of Python are basically 20 amorphisms written by a python. Simple is better than complex and complex isbetter than complicated. Errors should never pass silently unless explicitly silenced. Flat is better. than nested. If your code is written beautifully and it's not cluttered, then it will improve the readability of your code.
  • Pep eight is a set of guidelines which your code should be following. These include stylistic guidelines and naming conventions. It also includes guidelines for the commenting and doc strings in our Python code. Let's look at some of the aspects of web eight.
  • Another aspect of style guidelines is naming conventions for different constructs of the language. packages and modules should be named all lowercase, and you should use short names. Underscore can be used for readability, but using the underscore is discouraged.
  • Lint is a tool which collects the small particles or small defects from your code base to make it more readable, more maintainable, and more extendable. In programming languages or in programming projects, we have two kinds of lints. Some are implicit and some are explicit.
  • When to check or when to apply the linters to our code basis. Usually developers check in their codes at the end of the day. The last option is when running your tests. The best choice is to use the option of when it's checked in.
  • An idiom is a phrase that doesn't make literal sense, but makes sense once you are acquainted with the culture in which it arose. idioms are certain language constructs, language features, or language rules which all the programmers working in that language follow. Here are some common Python idioms.
  • We should use dot starts with and dot ends with instead of slicing for prefix or suffix checking. These are the beautiful python language constructs. These objects make resource management more explicit and safer. It separates business logic from administrative logic and make the writing business logic made more easy.
  • In idiomatic python you can use the Python list static operator to create simple and nested lists of the same value. List comprehensions provides a concise and easy way to create transform and filter lists. Use the list comprehension to create the whole list from scratch.
  • Dictionaries dictionaries are also an important data structures in Python. For these we have some common idioms. These are powerful constructs and should be used wherever they are required. These constructs should not be used for the sake of using them.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hello everyone, I'm Amara from Pakistan. I have been working with Python for more than six years now, and in today's talk I will be discussing about some common Python idioms and why it is important to write pythonic code, how it relates to the quality of the code, and what tools are available to check for the quality, or to make sure that your code is following the language guidelines. Let's get started. First of all, a brief outline. I will be discussing that what is pythonic and why it is important to write pythonic code? What is code quality and why it is important to measure what tools are available for Python programmers to make sure that their code bases are following Python guidelines. What is idiomatic Python? And in the end, I will be sharing some common pythonic idioms which I have learned through over the years. So let's get started. First of all, what is pythonic? Any program, function or block of code that follows style guidelines and make use of Python's unique capabilities or language features is said to be pythonic code. Snippet writing pythonic code is important because that determines that your code is of certain quality and certain standard. It follows language features and you are adhering to the language standard and industry standards for that language. It also counts for these quality of the code. And code quality is getting important day by day due to scarcity of the trained resources. Now, when we talk about quality of the code, what do we mean by that? If you quickly search through the Google can get to know that what are the attributes of a good code? Quality good quality code. But we can summarize them in the following points that it does what it is supposed to do. A certain code snippet is supposed to perform a set of basic requirements. If it is not performing those requirements, then it is not even a bad quality code. So it should be performing what it is supposed to do. Then there are known defects and problems. For this, I will take an analogy of these detergent you use to wash your clothes. If your detergent is working fine with day to day clothes which are not having any hard stains, but whenever a hard stain gets onto your clothes, this detergent cannot perform in getting rid of that stain, then your detergent is not of good quality. And the third and most important attribute of a good quality code is that it is readable, maintainable and extendable. It should be maintainable and extendable because over the time, as the requirements change and businesses processes grow, you have to add new functionality. If you are not able to extend your existing code, then you will have to rewrite the whole software again. And it should be readable because it is not necessary that the person who wrote the software first will be available to maintain and extend the software forever. You will be hiring new engineers and it should be readable enough so that new engineers or new developers can easily understand your code. So why code quality is important? Code quality is important because of the following reasons. First of all, clarity. If your code is not of good quality, then these will not give the clarity to the people who are working on the code basis. And it will not give the clarity that how a certain requirement is being accomplished through the code written. Then the second reason is efficiency. If your code is of bad quality and it is not readable, or maintainable or extendable, then the cost of maintaining such project or extending such project will skyrocket and your budgets will be affected. And it will not be efficient in terms of finances and human resources as well. The third important reason is the credibility. If you are following certain quality standards while writing your code, then it will add to your credibility as a programmer. But if you are not following the standards and guidelines, then your credibility as a Python programmer will diminish and that will definitely harm you in the long run. So as Python programmers, what tools are available to make sure that the code we are writing follows a certain set of guidelines and is of certain standard quality? There are a lot of tools available, but I will be discussing the following three the Zen of Python, pep eight and lenters. Let's talk about them one by one. Zen of Python. Zen of Python are basically 20 amorphisms written by a python. These Tim Peters, he wrote these beautiful, actually 19 amorphisms and left 20th, the last one to fill in by the creator of the Python language, Guido and Rossam. But it's still not filled in. Also, another Pythonista who has also contributed the Python language, Barry Warsaw, sang these amorphisms as lyrics in May 2020. And you can easily find that song on YouTube by searching the Zen of Python. This set of guidelines or this set of amorphisms is also included, as can Easter egg in the Python distribution. If you go to the Python shell and write import this, the Zen of Python get printed. Now, if we look at these morphisms one by one, these are basically a code set of principles which are being followed while writing the language. And it is expected from all the programmers using the language that they follow these simple principles. Let's start with the beautiful is better than ugly, because if your code is written beautifully and it's not cluttered, then it will improve the readability of your code. Explicit is better than implicit. For this, I will take the use case of naming the variables used in your code. The variables used in your code should follow the naming conventions set by the language, and also the names you are assigning to the variables should contain the context for which these variables are being used, so that everybody reading your code can understand that what variable is holding data for what purposes? Simple is better than complex and complex is better than complicated. You should try to use simple language constructs to solve simple problems. But if you have a complex problem and you cannot solve it by simple language constructs, then you can use a complex solution, but it should not be overly complicated. Flat is better than nested. This means that if you can avoid the nesting of tools, or you can achieve something by a flatter piece of code, then you should avoid undue nesting. One example of this can be avoiding nested loops by using the product method in iter tools module. Maybe sparse is better than dense, so this is related to spaces and indentation levels. Indentation spaces in the code base you are dealing with. If it is sparse, it has more spaces, then it is better for readability because readability counts. Special cases aren't special enough to break the rules, although practicality beats purity. Yes, you should not break the rules of the language to handle special cases in your project. But if those special cases cannot be handled without breaking the rules, then of course you have to follow the practicality. Errors should never pass silently unless explicitly silenced. This explains that you should be aware that what errors are being thrown by your code, and you should explicitly catch them and determine that what to do if certain error occurs. But if you want errors go unnoticed, then it should be explicitly silenced. That means you should write the catch block for try accept block, and you can write the pass statement in the accept block to silence the error. So all these beautiful amorphisms are basically a code set of principles which you can use to make sure that your code is following the basic guidelines recommended by actual Python developers who have contributed to the language creation like this one. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea, right? So next tool we can talk about is pep eight. Pep eight are basically what does pep stands for? PEp stands for performance enhancement proposals, and we can define these proposals as the documents to describe new features proposed and to document different aspects of Python like performance design and style for the community. These are basic set of guidelines which your code should be following. These include stylistic guidelines and naming conventions, how you should lay out your code, how you should format your code. We also have such kind of guidelines for the commenting and doc strings in our Python code as well. That is web two five seven. So let's look at some of the aspects of web eight. Let's talk about the code layout one statement per line you might know that we can write multiple statements in one line in Python, but we have to separate them by semicolon if we want multiple lines of code in one line. But it is strongly recommended that you use one statement per line, and that is the reason you can get rid of the semicolon at the end of each statement, which was really error prone in our college days of c plus plus projects and assignments. Single point of return while writting Python functions, you should consider to make sure that your function is returning from at the end of the function at the single point. Having multiple point of returns in a function will cause confusion, it will be more error prone, and for the future developers, it will difficult to understand that what you are returning from a function in every scenario indentation we know that Python syntax is strongly dependent upon the indentation. We can use two spaces per indentation level and four spaces per indentation level as well, but it is recommended that we should use four spaces per indentation level if you remember that sparse is better than dense from the Zen of Python. So if you are using four spaces then your code will be a little bit sparse and it will be more readable. Tabs or spaces for indentation you can use tabs or spaces. Tabs is of eight characters by default, but you can modify it to consist of only four characters. But by the Python creators it is recommended that spaces should be used for indentation instead of tabs maximum line length so this is kind of a strange requirement. But if you think about this requirement, then you get to know that these limit of 79 characters for a single line of code in a Python editor is actually because that you don't have to scroll from left to right again and again to read only one line of code. So it is limited to 79 characters only, and for the comments and doc strings it is further limited to 72 characters only. In web two five seven. You can find the guidelines for writing comments and doc strings in your Python code as well. Python has a rich libraries available to its programmers through which you can achieve various features and various tasks readily available. So to use these libraries you have to import those modules and libraries in your code. So it is recommended to include all the imports used in your code scripts at the top of the file and each import should be at a separate line. Multiple imports should not be included at single line. Wildcard imports are discouraged. Wildcard imports where you are importing everything from a module like import static is highly discouraged. There are further rules that you should include these modules from the standard library distribution at the top. Then you should include any third party libraries and at the end you should mention the imports which you are using from your own project. String quotes in Python you can define string rituals by single quote or double quote both. What is recommended whether we use single quote or double quote, you can use any of them single or double, but it is recommended that whatever you choose, you should be consistent throughout your code base. All your programmers should be aware that you should only use single quote or double quote to define string literals anywhere in your project. Another aspect of style guidelines I would like to cover here is naming conventions for different constructs of the language. First of all, packages and modules. These should be named all lowercase, and you should use short names. Underscore can be used for readability, but using the underscore is discouraged. Examples are like pandas models, iter tools, et cetera. Then we have classes. For classes we can use passport case which is in it caps as well. We should not include the world class while naming any class object. For example, if you want to define an employee class or student class, we should only name it as employee or student, not employee class and student class. The class keyword should not be included in the name of the class. Exception names exceptions are actually classes in Python, so the name is same. Naming rules applies, but using suffix error is recommended to make it explicit that this class is of exception like limit not expired error type error name error, et cetera. So error suffix readily tells you that this class is handling some kind of exception. It is not a regular class. Constants for this use all k apps snake case for example, database underscore URL, API key or base underscore URL. Like any other programming languages, constants are recommended to use all caps, nakes, functions, and variables. These can use standard snake case for example, all lower better, and you can use underscores to separate out the words in the names to make them more readable. For example, def final underscore score team underscore score like this function or method arguments. Now the arguments which are being passed to the functions or class methods. Those follow the same naming rules as the variables, but if you are writing an instance method, then its first argument should be self. If you are defining a class method, then its first argument should be CLS, that is class. And if you have clash with any of the keywords of the language, then you can use a trailing underscore to avoid this clash. For example, if you have a class in which you have an attribute which is named class, you should use it as class underscore instead of like misspelling it clss or clas. This is not recommended. Methods and instance variables for methods instance variables, same naming rules applies as of functions, but to segregate public and non public instance variables and methods, one leading underscore is used for non public and to avoid parent child clashes, we can use two leading underscore if we have same name variables and methods in parent and child both. The next rule I want to talk about is lenters. So before talking about lenders, I would like to take another analogy and describe about that. What is lint? Lint is actually the small particles which get stuck to our clothes when we wash them in washing machines. And that really is annoying that your clothes are instead of getting cleaned, they actually get dirty with those small particles stuck to them for their solution. For the solution of this problem, all the washing machines in our houses, we have lint filters installed which collect all these small particles, and your clothes come out neat and clean as required. So linter is basically a tool which collects the small particles or small defects or small unwanted things from your code base to make it more readable, more maintainable, and more extendable. In programming languages or in programming projects, we have two kinds of lint. One is logical lint. It includes code errors, dangerous code patterns, and code with potentially unintended results. Other type of lint is stylistic lint. This involves around code not conforming to conventions and style guides. So for making sure that these two kinds of lints are not present in your code basis, there are certain linters available in the Python ecosystem. Some are implicit and some are explicit. The linters of Python while writing or creating our projects, we all use certain ide for developing the Python projects. So ides are also a kind of linter which includes implicit filters or implicit linters to make sure that you are adhering to some basic set of guidelines adopted by the language. But these linters are basically mostly of stylistic type. Another example is pilot. This module is a linter which catches logical and stylistic errors. Then we have code style. This is purely stylistic, and it purely follows the pep eight guidelines. Then we have py doc style to make sure it is also stylistic and it follows the guidelines mentioned in pep two five seven and it purely checks only for the comments and doc strings in your code. Then we have PI flakes. This is purely logic. So how to use these linters? Ides have implicit id linters. You don't have to do anything, but all other linters you can quickly install them through pip install command and then you can write the command module name pylint and the file name. Press enter and you will have the list of errors and warnings which you should be looking at to make your python code more readable and more maintainable. The next question which comes to our mind that when to check or when to apply the linters to our code basis. So for first choices as you write it, you have written a small piece of code, a small function, a small code snippet. Just apply the linter, get the stuff done and you can get the errors corrected and you are done. The other option is when it's checked into the version control system. Usually developers check in their codes at the end of the day. So it is a nice idea to spare half an hour at the end of the day to apply the linters and make sure that the errors voted by the linter are resolved. And then you just check in the code to the version control system. The last option is when running your tests. This option is viable because you don't have to apply the linters every day or multiple times in a day. You will be just applying the linters by only twice or twice during the sprint cycles, but this will result in more effort in resolving the errors reported by these lenders. So in my opinion, the best choice is to use the option of when it's checked in. At the end of the day, when you are checking in your code, apply the linter, fix these errors, and get these desired code quality with minimum effort. Now I would like to talk about idiomatic Python. Before talking about idiomatic Python, let's see that. What do we mean by the idioms? An idiom is a phrase that doesn't make literal sense, but makes sense once you are acquainted with the culture in which it arose. So it doesn't have any literal meaning, it just acquires the meaning from its surroundings or the culture it is being used in. Similarly, for programming, an idiom is a thing you do daily for development in a particular language that are familiar and meaningful to those who work in these same language. So basically, idioms are certain language constructs, language features, or language rules which all the programmers working in that language follow to make sure that everyone is on the same page. Now let's look at some common Python idioms. First of all, swap variables without using temp variables if you remember your college days when we used to program in c plus plus to swap the values of two variables, we'll define a temp variable, assign the first variable to it, and assign the second variable to first variable, and then the temp variable to the second variable. So one, two, and three lines of code just to swap the values of the two variables. But in Python you can do it simple in one line of code just by swapping the order of the variables at both sides of the assignment operator. Do not compare directly to singletons like true, false, none, or zero. These are actually boolean literals, so you don't have to check them with the equality sign. The known idiomatic code will be checking these literals as if foo equal to equal to true, but the idiomatic python will be checking it like true or false as it is if foo is none. So this is the idiomatic way. Use is not instead of not is not is actually not intuitive and also confusing. If you are checking for negation, then you should be using is not operator instead of not is. The non idiomatic way is if not, foo is none. So this is not making sense. But the idiomatic way is if foo is not none. This is easy to understand. This is plain English and completely readable to anybody. Empty sequences are also false. This includes empty list, empty dictionary, or empty tuples. So these empty sequences also behave like just false Boolean literal, and you can check them in your code. As we treat the Boolean literals like if empty list, empty square brackets, repeating variable name and if statement. So let's take an example in non idiomatic way. We have a name Tom, and we want to check that if it is a generic name or not, or more commonly used name or not, then we will be checking if name equal to tom or name equal to dick or name equal to Harry. If it is one of them, then set these is generic name to be true. But what is the idiomatic way? Idiomatic way is to use the in operator. The name we want to check is Tom and we have a flag is generic name. We are checking it with the assignment operator. Name in true or false is returned through this in operator, and that is getting assigned to is generic name. So 1234 lines of code is collapsed two two lines of code only for loops in other programming languages, a typical way to write a for loop is define a variable, set it to zero, check for the container length and increment it in every iteration and in the curly brackets. Do whatever you want to do. In Python. You can achieve the same functionality by this code snippet for I in range length of my underscore list. Range function will be starting from zero to length and increment by one in every iteration. But what is the idiomatic way? The idiomatic way is to use the python in operator. That is for element in my underscore list and you are done. You don't have to worry about these maintaining the loop counter by yourself looping backwards again. In other programming languages, you will be starting the loop counter from the length and decrementing it in every iteration until you reach the zero. In Python, you can achieve this through this code snippet. Again, the range function. You will be starting with the length of list and writting the step to minus one for every iteration. What is the idiomatic way? The idiomatic way is to use reversed for element in reversed my underscore list. This is more efficient and more readable. Any layman can understand that we are traversing the list in the reverse order tracking index of for loop. What is the non idiomatic way? You will define a counter, set it to zero, and in each iteration you will be incrementing it one as you go through these list of elements. What is the idiomatic way? Use enumerate by enumerate you will get the index and element every time you read an element from the container list using for else syntax. This is actually a very interesting Python idiom and I got to know about it very late. But these it is. Let's take an example that we have certain users and we want to check that whether any user has entered his address or not. So we write this code snippet. We define a flag, traverse over the users, check if the user has entered the address. We set the flag to true and break the loop because we have found that at least one user has entered the address and at the end of the code we check for the flag to get to know that whether address was entered or not. So what is the idiomatic way? The idiomatic way is to use else clause for the for loop. Yes. Here is the code snippet. For each user we are checking that whether the user has entered the address if it has entered the address, we are printing our message and we are breaking out of the loop. But if the loop terminates by executing all its iterations and we have not found any address. Then we are coming to the else clause. So else clause is executed whenever the loop terminates by completing all its iterations. Otherwise we will be breaking in when we found the address using iter to check for sentinel value. So let's take an example. Over here we have a file which we want to read in chunks of 32 bytes. For that we are writing this code snippet. We have a list, and while we are not reaching the end of the file, we have not the empty chunk. We are reading 32 bytes in every iteration and appending it to list. What is the better way? The better way is to use the iter function. Again, we have defined a list in which we will be appending our chunks of 32 bytes, but we will be using the iter function in which we can give the sentinel value. Yes, the iter function can iterate over the list of elements and also can check for the sentinel value. Two break out of the iterations. It is better because it is more efficient. And yes, the first argument of the iter function is a function with no arguments for that. We are using the partial function which can reduce any function to zero. Arguments strings while using strings, we should use string method instead of the string module because they are fast and more efficient. We should use dot starts with and dot ends with instead of slicing for prefix or suffix checking. Why? Because slicing is more error prone and using starts with the ends with is less prone to errors. We should be using dot join while creating strings from list elements instead of using the plus operator. Yes, the non idiomatic way is to use for loop and a plus equal operator to every time concatenate the element two the string. But the idiomatic way is just to use the join method by passing the argument of the list to be concatenated context manager. These are the beautiful python language constructs. These are the objects to be used with the with statement, and these objects make resource management more explicit and safer. It separates business logic from administrative logic and make the writing business logic made more easy. Let's take an example. We want to read a file. For that we have to open the file. Then we'll read the file and these we have to explicitly close the file. But with the help of context managers you will not be bothering about closing the file explicitly use the with open context manager read the file and you are done. The with context manager automatically closes the file when you are done reading the file. Let's look at some of the other examples of context managers. Another example is, while we are using threading, for using threads we have to acquire log first log equal to threading log acquire, and then we execute a critical section. And in the finally block we have to explicitly release the lock. But with the context managers the better because you don't have to explicitly release the lock because if you forget to release the lock, you will be in a great mess. So with idiomatic Python or Python language constructs of context managers, you will just be acquiring the clock lock, and with lock context manager you will read the execute the recurring section and you are done. As you will be getting out of the context manager block, it will automatically release the log for you. Another example is you want to remove a certain file from your system, but what if that file doesn't exist? Your code will error out. So for that you will have to use the try accept block and cache the OS error. Whether you want to do something with it or not, it's up to you. But what is the better way? The better way is to use the ignored context manager with ignored and you specify the OS error and remove the file from your computer. Yes, we are not ignoring the errors, we are capturing the error with context manager with ignored and we are specifying that it is an OS error. Yes, we are passing it silently, implicitly silencing it. Other examples of context manager includes changing the standard output to a file instead of computer screens or monitors or lcds. For this you can use redirect sd out context manager. You will specify the file, and once you are done writing to the file, it will automatically shift back to the standard output of your computer. Another example is modifying some variable in temporary context. For that you will be using the local context context manager, and when you are done working in a temporary context, the context manager will shift back two the original context you were working in. Lists are an important data structure in Python language, so a lot of Python idioms are around these data structure. Let's talk about some of them. Creating a length and list of the same thing. How can you do this? One way to do this is by implementing a for loop. But in idiomatic python you can use the Python list static operator to create simple and nested lists of the same value. Let's look at the code snippet. Yes, you want to have a list of length five with every element set to hello. You can just write list equal to square brackets hello static five, and you can also create nested lists in the same fashion. List unpacking this is also a beautiful construct. You also use the static operator to represent the rest of the list instead of slicing because we have discussed earlier that slicing is more error prone. It is also a very nice and beautiful construct of the language, but in managing the indexes is really error prone and it is also less readable. The future programmers working on your code will not be able to understand that, why you are chunking out certain amount of data and what it is being used for. So what is the non edomatic way? You have a list abcde. You are only interested in first and second element and you're not interested in the rest of the list. So you'll assign some underscore list of zero index element to the first variable, second index variable element to the second variable, and the rest of the list two the rest variable through specifying the slicing index two columns. Similarly, you can be interested in the first and last only, and you are not interested in the middle of the list, and then you are interested in the middle element only and not in the head part or the last part. So this was a non idiomatic way. What is the idiomatic way? Idiomatic way is to use the static operator. Through static operator you will specify the variables which you want to extract and a garbage variable with static assigned to it. And on the right hand side of the assignment operator you will just write down the name of the list from which you want to extract these elements. So 1st 2nd static rest equals to some underscore list. The other two options can be followed out as above. Another option is using underscore as placeholder or throwaway variable. If you don't want to use any part of the list in the future, you can just replace the variable name with the underscore and that will not be accessible for future users. List comprehensions List comprehensions provides a concise and easy way to create transform and filter lists. These consist of brackets containing an expression followed by for and a conditional if clause. For and if clauses can change places. This means that you can write for first and then the condition, or you can write the condition first and then the iterator. It always returns result as a new list and the actual list is not modified. So the basic syntax according to these above rules is like expressions which we need to apply to every element of the list. Then we have an iterator, then we have a conditional. Another option is to switch these conditionals and iterator. Let's look at some of the examples. Double the value of each element in a list. What is the non idiomatic way you will write a for loop and for each item you will multiplying it by two. In this case you will be modifying the actual list and doubling the elements in the actual list. The idiomatic way is to use the list comprehension. We have a list. This is the expression x. Direct two is the impression for x. In ARR, this is the iterator and here we don't have any condition so this is more concise and beautiful way to create list. And a new list is being created and signed to ar. The actual list is not being changed. Another example, double the value for every even element in a list. So these non idiomatic way is again write a loop, check for every item that it is even or not and multiply the item by two if it is even. In this case we are again changing these actual list. We are dealing with what is the idiomatic way using the list comprehension x static two is the expression we need to apply to every element that is even. Then we have a conditional if x mod two equal to equal to zero, then multiply it by two else keep it as it is for every element in array and do this for every element in array. This is the iterator and a new list is being assigned to ARR generator expressions. All list comprehensions can be transformed into generator expressions, but how? Remove the square brackets, replace them with the parentheses, and you are done. Why we should be using generator expressions because these are more efficient in terms of performance compute and in terms of memory. Use the list comprehension creates the whole list from scratch. A new list is being created and assigned to the and is returned. But generator expression only evaluates the value which is required and it does not consume up the space for creating the new list. It is better and a lot more faster. Updating lists let's say you have a code base where you are using lists and you are mostly interested in the first elements of these list. So you will be deleting the first element, you will be popping out the first element and you will be inserting new elements at the start of the list only. If you are doing this with the list then your code will be damn slow. So what is the better way to do this? The better way to do this is to use the tech data structure DQ data structure. By this you will be deleting the first element by Dell command. Then you will be using the pop left to pop the first element and append left two append elements at the start of the list. But this will be a lot more faster. So wherever in your code bases. You have these kind of statements, go find them and replace them with the deck data structure and pop left independent commands. Dictionaries dictionaries are also an important data structures in Python, and for these we have some common idioms. First of all, we should use dict get method while retrieving values from the dictionary to specify a default parameter for default value if a value is not found. So let's look at the example, the non idiomatic way. We are checking for the debug levels in our code and what action is to be taken against a certain debug level. So we'll define the debug level equal to none, and we'll be finding out that if the critical level is found, then what action is to be taken. So if debug level is not found in the dictionary, then we'll be assigning the default value of info. What is the idiomatic way to do this? Idiomatic way to do this is using the get method. It's specifying the default value info if the required value is not found in the dictionary if the required key is not found in the dictionary. Actually, what are the use cases for this method? Counting with dictionaries let's say we have a dictionary. We have a list, colors in which we have red, green, blue, and we want to count the instances of each color name. We'll define a dictionary, traverse through the colors if a color is not in the dictionary, we'll be creating the key and assign a zero to it and increment it by one every time we find the same color. So the output will be blue two green two red three. So what is the idiomatic way? Idiomatic way is to define a dictionary and traverse over the colors for color and color, and use the get method by specifying the zero value if key is not found, and increment it if the key is found every time of the same color. Another way to do this is using the collections module. From collections we can use a default dict data structure. Through this data structure you can define a dictionary of certain type and it will assign value to all the defined keys to be an integer. If we are using integer, it will initialize it to zero. So you will be declaring the default dict of int type, and we'll be just traversing over the list for color and colors and incrementing the values if a certain key color is found. So for dictionaries like list, we also have dictionary comprehensions to build dictionaries more efficiently and beautifully. Examples are again, we have some users and some have added the address. Some have not added the address. We want to add users which have added the address to the dictionary. So we'll be writing the loop and checking for the address entered. If they have these, we will be creating a key with the username and assigning it the value of address. What is the idiomatic way? Idiomatic way is to use the Dict comprehension. For dict comprehension we use the curly brackets. User name is the key, users address is its value and this is these iterator for user and users and this is the condition if user address looping over dictionary keys how you can loop over the dictionary keys simple for k indent k. Another way to do this is for k inde keys print k and maybe delete some keys or some values. So which one is better and why? Yes, using the keys method is better because it is more efficient. It returns a whole new list of keys and if you perform some action on any key in these for loop, the original dictionary will not get affected. Looping over dictionary keys and values the simplest way to do this is okay d you have key and you can assign the value from with d of k. Another way to do is using the d dictionary items method. It will return all the key value pairs and you can use them as you want. The third way to do this is to use d iteritems. Yes, it will also return the key value pair and you can do whatever you want with this key value pair. Which one is the best and why? D items is better? Yes, it is better because you can change the keys and values and the original dictionary will not get affected. But is it best? No, the iteritems method is the best option because not only you can modify the dictionary without being original dictionary getting affected, but also it is an iterative method, it will not be consuming extra space. So that is all for Python common idioms. But these idioms and language features are there to increase the readability and maintainability of your code basis. These are not there to impress other developers or discourage or other developers that these are not writing pythonic or idiomatic Python. This is not to shame other developers and these language constructs and idioms should not be used for the sake of using them. Remember, if a problem can be solved through a simple solution, we should not opt for the complex or complicated solution. These are powerful constructs and these should be used wherever they are required only as Spiderman says that with power comes great responsibility. These are some of the references and further readings to more get familiar with the Python idioms happy idiomatic coding and thank you very much for listening to me.
...

Ammara Laeeq

Independent Professional

Ammara Laeeq's LinkedIn account



Join the community!

Learn for free, join the best tech learning community for a price of a pumpkin latte.

Annual
Monthly
Newsletter
$ 0 /mo

Event notifications, weekly newsletter

Delayed access to all content

Immediate access to Keynotes & Panels

Community
$ 8.34 /mo

Immediate access to all content

Courses, quizes & certificates

Community chats

Join the community (7 day free trial)