| Start |
|---|
| List multiplication and common references Consider the case of creating a nested list structure by multiplying: At first glance we would think we have a list of containing 3 different nested lists. Let's try to append
The reason is that This can be further corroborated if we print the memory addresses of the contained The solution is to create the inner lists with a loop: Instead of creating a single You can also do this. It causes a new empty list to be created in each
Don't use index to loop over a sequence. Don't: Do:
Use enumerate if you really need both the index and the element. Be careful when using "==" to check against True or False Do not check if you can, just do it and handle the error Pythonistas usually say "It's easier to ask for forgiveness than permission". Don't: Do: Or even better with It is much better because it is much more generic. You can apply Do not check against type Python is dynamically typed, therefore checking for type makes you lose flexibility. Instead, use duck typing (opens new window) by checking behavior. If you expect a string in a function, then use Don't: Do: Using the last way, Don't mix spaces and tabs Use object as first parent This is tricky, but it will bite you as your program grows. There are old and new classes in Don't: Do: In Don't initialize class attributes outside the init method People coming from other languages find it tempting because that is what you do in Java or PHP. You write the class name, then list your attributes and give them a default value. It seems to work in Python, however, this doesn't work the way you think. Doing that will setup class attributes (static attributes), then when you will try to get the object attribute, it will gives you its value unless it's empty. In that case it will return the class attributes. It implies two big hazards: If you set a mutable object as a default value, you'll get the same object shared across instances. Don't (unless you want static): Do : |
Mutable default argument This code behaves as expected, but what if we don't pass an argument? This is because default arguments of functions and methods are evaluated at definition time rather than run time. So we only ever have a single instance of the The way to get around it is to use only immutable types for default arguments: While an improvement and although The idiomatic approach is to directly check the argument against the |
| Changing the sequence you are iterating over A Note: The second element was not deleted because the iteration goes through the indices in order. The above loop iterates twice, with the following results: This problem arises because the indices are changing while iterating in the direction of increasing index. To avoid this problem, you can iterate through the loop backwards: By iterating through the loop starting at the end, as items are removed (or added), it does not affect the indices of items earlier in the list. So this example will properly remove all items that are even from A similar problem arises when inserting or appending elements to a list that you are iterating over, which can result in an infinite loop: Without the When using a In the above example, changing A If you are going to delete all the items in the list: Although simply resetting The above example can also be combined with Or to loop through a list while deleting elements that meet a certain condition (in this case deleting all even elements): Notice that you don't increment A contrary way to think about removing unwanted items from a list, is to add wanted items to a new list. The following example is an alternative to the latter Here we are funneling desired results into a new list. We can then optionally reassign the temporary list to the original variable. With this trend of thinking, you can invoke one of Python's most elegant and powerful features, list comprehensions, which eliminates temporary lists and diverges from the previously discussed in-place list/index mutation ideology. |
| Integer and String identity Python uses internal caching for a range of integers to reduce unnecessary overhead from their repeated creation. In effect, this can lead to confusing behavior when comparing integer identities: and, using another example: Wait what? We can see that the identity operation To be more specific, integers in the range This is a common pitfall since this is a common range for testing, but often enough, the code fails in the later staging process (or worse - production) with no apparent reason after working perfectly in development. The solution is to always compare values using the equality ( Python also keeps references to commonly used strings and can result in similarly confusing behavior when comparing identities (i.e. using The string For uncommon strings, comparing identity fails even when the strings are equal. So, just like the rule for Integers, always compare string values using the equality ( |
| Dictionaries are unordered You might expect a Python dictionary to be sorted by keys like, for example, a C++ Python doesn't have any built-in class that automatically sorts its elements by key. However, if sorting is not a must, and you just want your dictionary to remember the order of insertion of its key/value pairs, you can use Keep in mind that initializing an The implementation of dictionaries was changed in Python 3.6 (opens new window) to improve their memory consumption. A side effect of this new implementation is that it also preserves the order of keyword arguments passed to a function: Caveat: beware that “the order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon” (opens new window), as it may change in the future. |
| Variable leaking in list comprehensions and for loops Consider the following list comprehension This occurs only in Python 2 due to the fact that the list comprehension “leaks” the loop control variable into the surrounding scope (source (opens new window)). This behavior can lead to hard-to-find bugs and it has been fixed in Python 3. Similarly, for loops have no private scope for their iteration variable This type of behavior occurs both in Python 2 and Python 3. To avoid issues with leaking variables, use new variables in list comprehensions and for loops as appropriate. |
| Chaining of or operator When testing for any of several equality comparisons: it is tempting to abbreviate this to This is wrong; the Alternately, the built-in Or, to make it more efficient: Or, to make it shorter: Here, we use the Similarly, it is incorrect to write which should be written as |
| Accessing int literals' attributes You might have heard that everything in Python is an object, even literals.
This means, for example, Seeing the above code works, you might intuitively think that There are a few ways to access an Using two dots (like this This problem doesn't exist when accessing |
| sys.argv[0] is the name of the file being executed The first element of |
| Global Interpreter Lock (GIL) and blocking threads Plenty has been written (opens new window) about (opens new window) Python's (opens new window) GIL (opens new window). It can sometimes cause confusion when dealing with multi-threaded (not to be confused with multiprocess) applications. Here's an example: You would expect to see There are a couple ways around this. The first is to implement your factorial function in native Python. This will allow the main thread to grab control while you are inside your loop. The downside is that this solution will be a lot slower, since we're not using the C function anymore. You can also |
| Multiple return Function xyz returns two values a and b: Code calling xyz stores result into one variable assuming xyz returns only one value: Value of TypeError: type tuple doesn't define ... method The fix would be to do: Beginners will have trouble finding the reason of this message by only reading the tuple error message ! |
Pythonic JSON keys If you are used to JavaScript, variable evaluation in Python dictionaries won't be what you expect it to be. This statement in JavaScript would result in the In Python, however, it would result in the following dictionary:
|
Read Article
https://develop.horje.com/learn/1434/reference