When I started at Treehouse, I only had one mission: Teach Python. Seems easy enough. But I was immediately hit with a bit of a problem. Which version of Python should I teach? Python 2, started in 2000 and slated to lose all support in 2020, is still popular but it’s definitely going to end. Guido already declared there wouldn’t be an official 2.8. And Python 3, despite it’s slow adoption and early problems with Unicode, is now a strong version of the language. But I knew, I just knew, that if I picked Python 3, I’d get asked why.

They could have hired me for my psychic abilities.

Students haven’t asked quite as often as I expected, but it does come up. I figured I should explain why I picked Python 3 and what some of the major differences are between the two versions of the language.

Why Python 3

The answer I give most people is because Python 2 has been end-of-life’d. The people that work directly on Python have decided that there won’t ever be a Python 2.8. They also decided that Python 2.7, from now on, will only get security updates from the Python 3 development branch. No new features unless someone wants to spend the extra required time to backport them. Thankfully, several people are willing to do this. This has given us the amazing __future__ module full of Python 3 goodies, but that’s not the same as using them natively.

Another, somewhat embarrassing reason, is that I hadn’t had a lot of pure Python 3 experience. I wanted to be able to learn more of the newest version of my favorite language. Python 3 scared me when I first looked at it a year or so ago. It seemed like a big change for no real gain and I had visions of having to rewrite everything I had done to support this new interpreter. I was so wrong.

The impending death of Python 2. My desire to dive further into Python 3. The fact that using Python 3 would give us access to amazing new bits like asyncio. These reasons, and others, convinced me to just use it and nothing else here at Treehouse.

I made the right choice.

Even with all the changes that I’m going to talk about below, learning Python 3 won’t stop you from doing Python 2. Most of the code you’ll write will work on either system with some small caveats. You’ll need to remember to substitute raw_input() for input(). You’ll want to always extend your classes from object. And you’ll want to use the __future__ imports to get the new goodies from Python 3.

Favorite Differences Between The Two

Print is a Function Like It Should Have Been All Along

This right here is one of my favorite new things. When I was teaching Python as a corporate trainer, I’d show people the print keyword. I would then explain how print is secretly a function but doesn’t use parentheses like every other function in Python. Cue confusion when we get to any other function in the language.

In Python 3, print() is a function and has parentheses just like it’s supposed to. This, alone, makes getting into the language so much easier.

Unicode and Strings

Python 2 and 3 both have two types of strings. There are byte sequences which have to be literal characters from the ASCII alphabet. There are also Unicode strings, which can hold onto pretty much any character you want to put in there. In Unicode, you can include other languages and, with the right encoding, emoji. But in Python 2, you had to mark every single Unicode string with a u at the beginning, like u'Hello'. Guess how often you use Unicode strings? All the time! Guess how often you forget to put that little u on a string? Forget the u and you have a byte sequence instead.

So, with Python 3, they fixed it. All strings are now Unicode by default and you have to mark byte sequences with b. Using Unicode is a much more common scenario so it has reduced development time for everyone that does Python 3.

If you have or want to support both, you can still mark strings with u in Python 3, though.

Division With Integers

You would think that math is one of the things that programming languages just get right. And most of the time, you’d be right. But division was a weird one in Python 2.

One of Python’s core values is to never do anything implicitly. You shouldn’t turn a number into a string unless the programmer tells you to, for example. But Python 2 took this a bit too far. Consider this problem:

5 / 2

For most of us, our immediate answer is 2.5, which is, of course, the right answer. But Python 2 said “oh, you only gave me integers so you must want an integer back” and happily returned 2. Well, yes, I did give you integers, but I’d rather have a correct answer than an answer that matches my data types.

Again, Python 3 fixed this. Python 3 will give 2.5 as the answer to that question. In fact, it gives a float (a number with a decimal in it) to every division operation.

input() is Now Safe to Use

And, finally, Python 3 brought an important change to the input() function.

In Python 2, there was a raw_input() function and an input() function. raw_input() was the one you always wanted to use. input() was a great way to have your code do things you didn’t want it to. The reason for this is that input() evaluated whatever came in. So good users would send in 123 and Python, trying to be helpful, would make that into an integer instead of a string. Bad users would send in little, or not so little, bits of Python which would then be evaluated, or run. Cue your software doing things you didn’t ask it to do.

In Python 3, raw_input() is gone and input() no longer evaluates the data it receives. You always get back a string, as we’ve seen in Python Basics.

I didn’t even bring up tab completion in the shell. Or the new next() function for generators and iterators. Or yield from. Or how xrange() became range(). Or for-loop variable leaking, and… yeah, you get the idea. Here’s a great overview to show you even more of the reasons it’s worth it to upgrade to Python 3. It has proven to be an amazing version of the language and I can’t wait to share more of it with you. Also, about adoption, we’re getting closer every day.