One Code to Run Them All (Python 2 and Python 3)

Quite a while ago, I decided to do all my Python programming in Python 3 as much as possible. This is essentially always for the typically small stand-alone programs that I put on this blog. I did this to encourage people to use Python 3 for their own work, and to be future proof. Additionally, a “unified code” approach, where you write code that works on both Python 2 and Python 3, seems like it could delay the transition to Python 3, simply because all code needs to stay compatible with Python 2. Hence, I started each program with the following, and kept it at that:

# All scripts on TomRoelandts.com assume Python 3.

However, in practice, people kept finding the programs on this blog and on fiiir.com and ran them in whatever version of Python they happened to be using.

Given that my example programs typically compute numerical stuff, this mainly causes problems with the division operator. If I add the fact that the print statement from Python 2 has become a print() function in Python 3, then the following statement seems to be the archetypical example of problematic code, if you run it in Python 2 instead of in Python 3 as intended:

# Executed in Python 2:
>>> print(1 / 2, 3 / 4)
(0, 0)

There are two unexpected things in the output. The first one is that a tuple is printed. This is because the print statement in Python 2 does not need brackets, so it interprets (1/2, 3/4) as a tuple. The second, more eye-catching problem, is that both results are zero. In a statically typed language such as C, you expect this if you divide two integers. However, in a dynamically typed language such as Python, it is unexpected. Hence, this behavior was changed in Python 3:

# Executed in Python 3:
>>> print(1 / 2, 3 / 4)
0.5 0.75

Personally, I think that the best way to write “unified code” is the “borrow from the future” approach. Both the division operation and the new print() function can be imported as follows, for results that are the same in both versions of Python.

# Executed in Python 2 or Python 3:
>>> from __future__ import print_function
>>> from __future__ import division
>>> print(1 / 2, 3 / 4)
0.5 0.75

I’m aware that you can also change the constants to floats (or cast them if they are variables) , but that seems a bit of an ugly solution for a language such as Python, I think. Also note that there is the floor division operator (//) that you can use to do integer division as nature demands it. The term is floor division intead of integer division, since also 1.0//2.0==0.0.

Anyway, I still would like to encourage you to use Python 3 for your own software as much as possible! In the meantime, I’ll try to adapt all Python programs and fragments on this blog and on fiiir.com to support both Python 2 and Python 3…

Tags

Add new comment

The content of this field is kept private and will not be shown publicly.
Spam avoidance measure, sorry for this.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Submitted on 26 January 2019