For a good few years we’ve been developing software in Python. Today we want to share with you the basics of crucial good practices we’ve been implementing - and we recommend you to do it as well.
Python, has currently been on the top position in the ranking of most popular programming
languages ; it is considered simple, easy and enjoyable. It won’t be an
exaggeration if I say it is even perfect for people who want to start their adventure with
programming. It is well suited for numerical calculation, developing web applications, and
writing quick console scripts.
Clarity and conciseness of the Python language helps to avoid many mistakes, but unfortunately not all. Below we have collected pieces of a code that may - or may not - cause interpreter errors, but surely sooner or later it will be a burden for you or the person that inherits the code from you.
As a side note, despite numerous associations the name Python doesn’t come from a friendly animal, but from well-known British comedy series Monty Python's Flying Circus broadcasted in the 1970s. The creator of the programming language Guido van Rossum was a big fan of the series and the language is playful and fun to use as well.
0) Style guidesPEP8 or other style guide (eg. Google Python Style guide  ).
We don’t need to convince anyone that code, which does not contain its own structure, looks very bad. For this instance, in good restaurants the dishes served are beautifully decorated, therefore you should serve your code the same way, even if the only person who reads it is the one checking pull requests.
Don’t be afraid of white spaces. This is not just a requirement of Python syntax, but also a huge convenience for other people reading the code.
1) Beware of mutable objectsAvoid mutable objects as the default arguments in functions or methods.
Try to run this code:
running this feature for the first time one gets the result consistent with the assumptions:
but calling the function for the second time one gets the result, which can cause a lot of strange and hard to debug errors:
|['some string', 'some string']|
and for the third time we get this:
|['some string', 'some string', 'some string']|
and so on...
Always use immutable objects
See how you can improve the foo() function, so it will become harmless:
|if unmutable_object is None:|
|unmutable_object = |
from now on when you call foo() function it will return exactly what you want:
This error occurs because the default values are evaluated only once, when defining the
function. Later throughout the lifetime of the function you use the same mutable object.
Other errors associated with this aspect of language can occur when the default argument of a function is another function.
|>>> import datetime|
|>>> def print_time_now(now=datetime.datetime.now()):|
|... print now|
The print_time_now function will always return the time, in which that function was defined:
|#after two years|
2) Handling ExceptionsCatching Exceptions in Python 2.x is a standard procedure: try, except and optionally finally.
However, in the except block a certain linguistic nuance appears, that may give less experienced developers a headache.
If you want to catch more than one exception you do it as follows:
|except (TypeError, IndexError)|
The attempt of catching an exception through except TypeError, IndexError (without the parentheses) causes catching only TypeError exception, and the IndexError exception won’t be caught and will generate an error.
3) Avoid except without definipng an exception
Continuing the catching exceptions topic, pay attention to the following piece of code: except without defined exception. If you notice any, immediately refactor it because it is like a bomb with a delayed ignition:
The above code snippet will cause errors in various, sometimes very strange situations.
4) Avoid the import with an asterisk
If you import with an asterisk you must be very careful because you might encounter a very popular Python error - a loop.
I always advise against importing the following way:
|from foo.bar import *|
It is much better for our future mental health to import modules this way:
|from foo.bar import bar1, bar2|
You can intentionally use "import by star" if in the file you want to import you put the variable "__all__" as in the example below:
|__all__ = ['bar1', 'bar2']|
Then, even if you use the from foo.bar import * only two functions bar1 and bar2 will be imported. bar3 function will not be imported.
Hope that the post was useful and clarified some Python language aspects. If you still have any questions dont hesitate and ask them in comments, I will try to explain it in more detailed way. The second part of "Python - good practices" you will find soon.