What's new with Python? A guide to Python 3 and beyond

Sep 24, 2020 - 10 min read
Ryan Thelin

Updating from one version of the Python programming language to another can be a real hassle. It’s even more difficult if you’ve missed a few versions in-between. What’re the most important differences? How do they compare with the version you’re familiar with?

Today, we’ll answer all those questions from Python 3.0 to Python 3.8. We’ll walk you through all of the biggest changes, how this compares to previous Python versions, and show you code examples to help you implement your own modern Python code. At the end of the sections, you’ll get a downloadable cheat sheet to take with you as you continue your Python software journey.

Today, we’ll go over:

Skip the learning curve and master Python 3.0 quickly

Use interactive examples and targeted lessons to speed up your transition to Python 3.

Mastering the Art of Programming in Python 3

Python 2.x vs Python 3.0

Python 3 made a lot of changes to simplify Python’s syntax and add new functionality. Each of these changes may seem small, but together they can seriously affect the way your program works.

Overall, Python 3.x has:

  • Cleaner syntax
  • More reliable mathematical and logical operators
  • More versatile String behaviors
  • Stricter data type rules
  • More modern support

Next, we’ll look at the important syntactic changes to help you adapt to Python 3.


In Python 3.0, the print behavior changed from a statement to a Python function. The print field must now be within parentheses like a parameter to work correctly.

print "hello, world"  # Python 2

print("hello, world") # Python 3

The change from the print statement to print function also affected some common print behaviors like line breaks and print to file.

In all versions of Python, each print call ends with a line break. However, sometimes you’ll need to print to the same line.

In Python 2, you could print to the same line with a trailing comma:

# Python 2 
print 5,
print 10

In Python 3, you instead use the end keyword argument after the first line.

# Python 3
print(5, end =" ")

Finally, Python 3 made the syntax to print to a file more readable.

print >>open('test.txt','w'), "Printing to file" # Python 2

print("Printing to file", file = open('test.txt','w')) # Python 3

Python 3's version does away with the `>>` symbols in favor of the more intuitive `file=`. It also rearranges the order of the arguments to match the business logic of the operation as we'd say "print ___ to file ___" over "to file ___, print ____".

Strings in Unicode vs ASCII

In Python 2, all strings are stored as ASCII by default. They can be stored as Unicode using the u in front of the string.

#Python 2
default = "This string is ASCII"
unicode = u"This string is Unicode"

In Python 3, all strings are stored in Unicode by default. Unicode is favored over ASCII across the world because Unicode supports variable bit encoding and more character sets.

# Python 3
unicode = "This string is Unicode by default"

Python 3’s change to support Unicode by default ensures that you always use the better encoding protocol unless you specifically opt-out.

Integer division

Division between two integers in Python 2 would round by default to the nearest whole number. Python developers had to constantly keep this in mind to prevent odd behavior in their programs.

Now in Python 3, the operation dynamically shifts data types to a float when the result is a decimal value. Each quotient will now reflect the true mathematical value without rounding. You no longer have to remember the fine points of an operation and can instead focus on your project.

For example:

# Python 2
print 7 / 5
print 7 / -5

Range vs xrange

Python 3’s range() function replaces the Python2 xrange() function. The new, cleaner function achieves the same outcome.

In Python 2, range() returned a list while xrange() returned an xrange iterator object. For most situations, these could be used interchangeably. Now, the Python 2 range() behavior has been removed.

for x in xrange(1, 5):  

Error handling

Python 3 now requires the as keyword when you implement error handling. This change separates error handling syntax from function parameter syntax and makes error handling code easiest to read at a glance. Many developers transitioning from Python 2 to Python 3.0 overlook this small but important change.

 # Python 2
except NameError, err:  
    print err, 'Error Caused' 

  # Python 3
except NameError as err: # new `as` keyword
     print (err, 'Error Caused')  

Source code and library compatibility

Python 2.x code can be forward-compatible with Python 3 but often creates unexpected behavior. Python 3 code, however, cannot be run in with Python 2.

While Python 2.x code can be ported, libraries often cannot. It can be difficult and unreliable to port Python 2 libraries to Python 3. As more users continue to adopt Python 3’s new features, most developers no longer create or update libraries from Python 2.

You’ll eventually have to transition to Python 3 if you want to use the newest tools and techniques from modern libraries, packages, and modules, especially those used for machine learning.

For example, Django requires modern libraries to work. As a result, Django no longer supports Python 2.x versions with updates. Django 1.11 was the last version to support Python 2.7. Django now recommends you download the newest version of the Python programming language for the best web development features and experience.

Python 3 CheatSheet


Keep learning about Python 3.0

Get the tools you need to learn Python 3 fast. Educative’s text-based courses are skimmable and targeted to the skills you need most to succeed on your personal and professional projects.

Mastering the Art of Programming in Python 3

Python 3.7 vs 3.8

The most recent version of Python is version 3.8. Whether you’re coming from Python 2 or an earlier version of Python 3, it’s important to understand the newest features available in this powerful update.

Below, we’ll walk through the biggest changes from Python 3.7 to 3.8 with code examples and explanations to help you use the most modern version of Python, regardless of which previous version you’re experienced with.

Assignment Expressions

The assignment expressions are the biggest feature added in Python 3.8. With these expressions, you can assign and return a variable’s value in just a single line. Assignment expressions are written with the new walrus operator, (:=).

Here’s an example:

var = 'False'
print var
# False

Instead of using two lines, we use the walrus operator to set and print the value of var in the same line. This type of structure has great potential in large, multivariable solutions, especially when used as a temporary variable in a loop.

Take a look at how much we can simplify this more complex program:

shoppingList = list()
while True:
    current = input("Next item: ")
    if current == "end":

Here we use the walrus operator to create the temporary variable current that is assigned as a string of the user’s input. It’s also evaluated at assignment to see if it matches “end”. The program repeats through the loop and adds the new item to the list’s end.

This program can create an entire input-driven list with just 3 lines of code!

f-String Debugging

The relatively new “f-strings” also received an update in Python 3.8. As a refresher, f-strings are a simplified way to print statements with evaluated variables without manually concatenating strings. Introduced in Python 3.6, they’ve become one of the most popular parts of modern Python. In fact, they’re considered the main reason that so many Python libraries are only compatible with versions after 3.6.

F-strings are a formatted string literal recognizable by an f before the opening quotation of the string. Any variable name within curly brackets is evaluated, and its value is seamlessly added to the string.

Take a look at an example:

size = "small"
print( f"This is a {size} dog")

This allows you to easily create dynamic strings without cluttered syntax.

As of Python 3.8, you can now add = after a curly bracket variable to print both the expression and variable.

size = "small"
print( f"{size= }")

This is most helpful for debugging, as it allows you to see how the program reaches these values.

In versions before 3.8, you’d have to repeat the expression before the curly brackets to get the same effect:

size = "small"
print (f"size = {size}")

You can also use assignment expressions within f-strings to create compact and dynamic strings:

print(f"Square has area of {(area := length**2)} perimeter of {(perimeter := length*4)}")

Positional-only arguments

In Python 3.8, you can now define positional-only arguments for your own functions. Positional-only arguments can only be assigned by their position in a function’s argument and will throw an error if you try to assign them through keywords. You use the symbol / in a function’s arguments to denote that all previous arguments should be positional-only.

For example:

>>> def parkingSpace(name, /, space= "Guest Parking"):
...     return f"{name}: {space}"
>>> parkingSpace("Ryan")
# `Ryan: Guest Parking'

>>> parkingSpace("Jodie", space= "14G")
# 'Jodie: 14G'

>>> parkingSpace(name="Joe", space="9B")

 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
 TypeError: parkingSpace() got some positional-only arguments passed as
            keyword arguments: 'name'

On line 1, we specify that name must be passed positionally (behind the /), while space must be passed with its keyword. On line 4, we successfully call parkingSpace and positionally assign the value of name with a default value for space. On line 7, we successfully call parkingSpace again, but this time, we assign a new value to space with its keyword. Finally, on line 10, we call parkingSpace a third time but assign name with its keyword rather than positionally and get an error.

Positional-only arguments allow for advanced functionality but are not always needed.

Use positional-only arguments when:

  • The argument title is arbitrary such as an int constructor, int (x="1") gives no more information than just int("1").
  • The argument title is also used by a built in function, like self. Positional-only arguments remove confusion on what is being passed.
  • You’re porting code from C or will do so in the future. C does not accept keyword arguments so using positional-only arguments will make porting easier.

Syntax warnings

Python 3.8 adds two new warnings to Python’s list of SyntaxWarnings. The first is a warning that will tell you when to choose is over ==. These are slightly different and easy to mix up. The latter checks for equal values, while is returns True only they’re the same objects.

>>> # Python 3.8
>>> version = "3.8"
>>> version is "3.8"
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
# returns False
>>> version == "3.8"
# returns True

The other warning is a revised SyntaxWarning when you miss a comma in a list. In previous versions, missed commas in a list of tuples would result in an error, stating “tuples are not callable”. This confused Python users, as most of the time, they were just missing a comma.

Now, Python 3.8 correctly identifies the error:

>>> [
...   (1, 3)
...   (2, 4)
... ]
<stdin>:2: SyntaxWarning:'tuple' object is not callable; perhaps you missed a comma? 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'tuple' object is not callable

Python 3.8 cheatsheet


What to learn next

You just learned all the most important updates in Python 3 and 3.8. If any of these changes sound appealing, I encourage you to update now and start implementing these new features. It’s important to be a modern, up-to-date Python developer.

Even if you’re not interested in any particular feature, Python gets faster and less memory intensive with each update. If you make the change now and practice new syntax, you’ll be able to show off your up-to-date skills to an interviewer!

To help you get over the learning curve with Python 3, Educative has created the course for Python developers looking to make the shift. Mastering the Art of Programming in Python 3 is full of practical examples and skimmable, text-based explanations to make your transition to the newest version quick and painless.

Happy learning!

Continue reading about Python


Join a community of 500,000 monthly readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.