5 easy tips for switching from Python 2 to 3

Practicus AI
Towards Data Science
5 min readJul 15, 2019

--

Source

I write a newsletter for learners called Mighty Knowledge. Each new issue contains links and key lessons from the very best content including quotes, books, articles, podcasts, and videos. Each and every one is picked out specifically for learning how to live a wiser, happier, and fuller life. Sign up for it here.

The Apocalypse is drawing near……

No, it’s not the end of the world….. it’s the end of Python 2!

Python 2 will officially be retired and will not be maintained past January 1st, 2020. The news is horrific for some (old school Python 2 users) and a huge relief for others (the cool Python 3 users).

So what does this mean for those who code in Python? Are you forced to switch over to Python 3?

Practically speaking, the answer is a definite yes.

Many of the major Python projects have signed a pledge to move completely to Python 3 and deprecate Python 2. We’re talking about some of the real heavy-weights in very common applications:

  • Data Science: Pandas, Numpy, Scipy, etc
  • Machine Learning: TensorFlow, Scikit-Learn, XGBoost, etc
  • Web: requests, Tornado
  • Many many more

Needless to say, with all of these major libraries doing a full switch to Python 3, updating your code base becomes a practical necessity.

In this article, I’m going to share with you 5 easy tips for switching from Python 2 to 3 that’ll make the transition a smooth ride.

(1) Imports

Python 2 used relative imports while Python 3 now uses absolute imports to make things more explicit.

Consider the following example folder structure:

py_package
├── main_code.py
└── helper_code.py

With Python 2’s relative imports, the import statement is written relative to the current file. For example, if we wanted to import some helper code into our main code we would do something like this:

from helper_code import help_function

Python 3 no longer supports this style of importing since it’s not explicit whether you want the “relative” or “absolute” helper_code. If there was a Python package named helper_code installed on your computer, you'd get the wrong one!

Python 3 now requires you to use explicit imports which explicitly specify the location of the module you want to use, relative to your current working directory. Thus, importing your helper code looks like this:

from .helper_code import help_function

Notice the new . beside the package name, which specifies that the package resides in the current folder. You can also do something like ..helper_code which tells Python that the helper_code package is 1 directory up from the current one of main_code.py . The main point is that Python 3 requires you to specify the exact package location.

(2) Print statements

The dreaded Python print statements!

Most of us have run into an error related to Python print statements at one time or another. It’s a change that will 100% require anyone using their Python 2 print statements to switch to the Python 3 style.

# Python 2 style
print "Hello, World!"
# Python 3 style
print("Hello, World!")

Basically, you’ll have to put brackets for all of your print statements throughout all of your code. Luckily, once you’re print statements have the brackets, they’ll work with both Python 2 and 3.

(3) Integer division

In Python 2, you would divide integers using the / operator and the result would be rounded down to the nearest integer. If you wanted the result to be a floating point number, you would first have to convert the numbers to float and then perform the division.

Python 3 gets around the need for having to do an explicit convert to float by using 2 different operators: / for float division and // for integer division.

### Python 2
a = 3 // 2 # Result is 1
b = 3 / 2 # Result is 1
c = float(3) / float(2) # Result is 1.5
### Python 3
a = 3 // 2 # Result is 1
b = 3 / 2 # Result is 1.5

The use of explicit operators in Python 3 makes code much cleaner and more readable — we know exactly that // is for integers and that / is for floats, without having to do explicit type conversions.

The new division operator is definitely something to watch out for. If you forgot to convert from the / to // for integer division when going from Python 2 to 3, then you’ll be getting floats where you originally had integers!

(4) String formatting

The syntax for string formatting is now much cleaner in Python 3. In Python 2, you’d use the % signs like so:

"%d %s" % (int_number, word)
"%d / %d = %f" % (10, 5, 10 / 5)

There’s a few things to note about those Python 2 statements:

  • The types of the variables is explicitly specified (%d for int, %s for string, and %f for float)
  • The string statement and variables are written separately, side by side
  • The style itself is very similar to Python 2 prints; no brackets, % signs for inserting variables, etc

Python 3 now uses what’s called a string formatter which is contained in the Python string class str.format() . The string formatter lets you concatenate elements together within a string through positional formatting.

"{} {}".format(int_number, word)
"{} / {} = {}".format(10, 5, 10 / 5)

With the new format() function, there’s no need to specify type at all and everything is written in one clean statement. All you have to do is make sure that the variables are in order and all will run smoothly.

(5) Returning iterable objects instead of lists

Many built-in functions now return an iterator instead of a list in Python 3. The main reason for this change is that iterators usually have more efficient memory consumption than lists.

When you use an iterator, the elements are created and stored in memory on an as needed basis. That means, if you have to create 1 billion floating point numbers using an iterator, you’ll only be storing them in memory one at a time. If you wanted to create a list with 1 billion floating point numbers you’d have to make sure you have enough RAM, since the data will be stored in memory all at once.

In many cases, the behaviour of using an iterator vs a list will be the same. One example of this is when looping through the output of the range() function.

# Python 2 range() function returns a list
for i in range(10):
print(i)
# Python 3 range() function returns an iterator
for i in range(10):
print(i)

Notice how the syntax is the exact same even though when we use Python 3 we have an iterator. The one thing to be careful of is that if you do specifically want to have a list, all you have to do is convert the type directly: list(range(10)) .

Some more commonly used functions and methods that return iterators instead of lists in Python 3 are:

  • zip()
  • map()
  • filter()
  • Python dict()’s methods: .keys() , .values(), .items()

Like to learn?

Follow me on twitter where I post all about the latest and greatest AI, Technology, and Science! Connect with me on LinkedIn too!

--

--