July 24, 2017

Python good practices – part 2

by Marta Dunajko

We’ve been sharing with you the good practices we implement when programming in Python. If you haven’t read it yet, the first part of the article you will find here.

Let’s continue!

5) The world of Python is now astride. Two branches of Python, namely 2.x and 3.x, are developing simultaneously. Some but not all libraries have already been ported to Python 3.x. Remember not to use features that are deprecated, because in the future it will complicate running code on Python 3.x.

6) The creators of Python have placed an "easter egg" in the Python interpreter, which contains a collection of good patterns. We advise you to try to implement them in your projects. You don’t have to apply all right away, but remember "now is better than never".

import this
view raw import.this.py hosted with ❤ by GitHub
  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • Special cases aren't special enough to break the rules.
  • Although practicality beats purity.
  • Errors should never pass silently.
  • Unless explicitly silenced.
  • In the face of ambiguity, refuse the temptation to guess.
  • There should be one-- and preferably only one --obvious way to do it.
  • Although that way may not be obvious at first unless you're Dutch.
  • Now is better than never.
  • Although never is often better than right now.
  • 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.
  • Namespaces are one honking great idea -- let's do more of those!

The creators of Python implemented also anti-patterns explaining what the code shouldn’t look like. Pay particular attention to the point: "Write optimal code before releasing." This is a trap developers often fall into.

import not_this
view raw import.not.this.py hosted with ❤ by GitHub
  • Write ugly code.
  • Write implicit code.
  • Write complex code.
  • Write nested code.
  • Write dense code.
  • Write unreadable code.
  • Write special cases.
  • Strive for purity.
  • Ignore errors and exceptions.
  • Write optimal code before releasing.
  • Every implementation needs a flowchart.
  • Don't use namespaces.
7) The scope of variables in Python is generally intuitive and simple, however it has a few dark sides that may cause errors. Let's start with a simple function.

>>> bar ='zuch'
>>> deffoo():
...print bar
view raw bar.zuch.py hosted with ❤ by GitHub
Calling this function won’t surprise you and you will get the word 'zuch'.

>>> foo()
view raw foo.zuch.py hosted with ❤ by GitHub
Let’s modify it a bit by adding one inconspicuous line

bar = 'puch'
view raw bar.puch.py hosted with ❤ by GitHub
at the end of foo function

>>> bar = 'zuch'
>>> def foo():
... print bar
... bar = 'puch'
The function should write 'zuch' and then change the word 'zuch' to 'puch'. But it doesn’t happen, because most variables in Python are local, and Python is not an interpreted language which executes the code line by line. Therefore, when Python analyzed the entire declaration of foo function, it found that the bar variable is a local variable, and when you wanted it to unsubscribe:

... print bar
view raw print.bar.py hosted with ❤ by GitHub
it returned an error

UnboundLocalError: local variable 'bar' referenced before assignment
view raw console.log.py hosted with ❤ by GitHub
because it has not been defined yet. There are two solutions to this problem:
A) Don’t use global variables unless you really need it. Remember about this, not only when programming in Python. Nobody likes global variables, so think about the people that will inherit the code after you.
B) When the situation will force you to use it (e.g. you’re maintaining the old code) use the keyword global. The above example can be modified as follows:

>>> bar = 'zuch'
>>> def foo():
... global bar
... print bar
... bar = 'puch'
>>> foo()
>>> bar
view raw bar.zuch.puch.py hosted with ❤ by GitHub

[1] http://blog.amir.rachum.com/blog/2013/07/09/python-common-newbie-mistakes-part-2/