Python 3.9 introduces some significant new syntax and standard library/built-in features. At the same time, it does away with some older conventions that have held it back and drop support for Windows 7. Luckily for those that are still migrating from Python 2, Python 3.9 still retains at least some of the Python 2 backward compatibility layers that provide deprecation warnings. However, this is likely to be the last version of Python 3 that will.
In this article, I’ll introduce many of the most important features/changes (with a few examples of some of them), including:
- Dictionary Union Operators
- String Methods
- Generic Types for Type Hinting
- Python Parser
Install ActiveState’s Python 3.9 for Windows or Linux and try it for yourself. It comes with with the Python 3.9 core, plus our command line interface, the State Tool to help you manage your environment. For more information on using the State Tool, refer to the Quick Start guide.
Dictionary Operators: Merge & Update
There are two new operators for the dictionary class: the merge operator (|) and the update operator (|=). As one might expect, the merge operator will merge dictionaries:
a = {1: 'a', 2: 'b'} b = {3: 'c', 4: 'd'} c = a | b print(c)
Output:
{1: ‘a’, 2: ‘b’, 3: ‘c’, 4: ‘d’}
Likewise, the update operator will update the dictionary:
d = {3:'cat'} c |= d print(c)
Output:
{1: ‘a’, 2: ‘b’, 3: ‘cat’, 4: ‘d’}
Both of these operators will simplify the implementations that were used to obtain the same results in previous versions of Python. The second dictionary will take precedence over the first, so if any keys are identical, the second one will be used in the final output. Further details can be found here.
New Python String Methods
Two additional string methods will be added to the string class: str.removeprefix(prefix) and str.removesuffix(suffix). These can be used to easily remove an unnecessary prefix or suffix from a string. For example:
"Hello world".removeprefix("He")
Output:
‘llo world’
or:
"Hello world".removesuffix("ld")
Output:
‘Hello wor’
These are pretty straightforward, but more information can be found here.
Built-In Generic Types for Type Hinting
Whether you are new to Python and learning for the first time, or a seasoned programmer with hundreds of lines of code to sift through, type hinting is a useful feature that can save you time and increase your code readability.
When defining a function, for example, it is useful to specify the type of input that a function argument can take (such as a string or list). In previous versions of Python, this function would have looked something like this:
def greeting(name: str) -> str: return 'Hello ' + name
The function greeting expects a string input (although other types are still accepted). When using a third-party type checker or IDE, it will indicate a warning if any other input type is given. If you want to specify a more complex input type such as a list of strings, previous versions of Python required the support of the typing package:
Notice that we had to import the List type from the typing package instead of using the built-in list type. With Python 3.9, this is no longer necessary. A complete list of standard collections that are natively supported can be found here.
from typing import List Vector = List[float]
def scale(scalar: float, vector: Vector) -> Vector: return [scalar * num for num in vector]
New Python Parser
Previous versions of Python used a parser based on the LL Parser (LL). This type of parser is pretty standard for most programming languages – it parses code top-down and left-to-right, with a lookahead of one token. For a language with limited complexity, an LL parser is usually more than sufficient, and it’s often the most efficient type of parser.
However, to maintain and hopefully improve the celebrated flexibility that Python offers over other languages, Python 3.9 is switching to a parser based on Parsing Expression Grammar (PEG) instead of LL. Given the number of hacks that have been implemented in the past to circumvent LL limitations, the PEG parser will likely require work to remove the hacks, but longer term will reduce maintenance work in the compiling pipeline. These limitations exist because the LL(1) parser is fundamentally context-free, which can lead to ambiguities when parsing. In contrast, the rules governing PEG are ordered so that these ambiguities cannot arise.
Note that while Python 3.9 introduces the PEG parser, new features that actually utilize its advantages won’t be implemented until later versions. For a more detailed explanation of the differences between the two parsers, read PEP 617.
Other Changes
There are a number of minor changes also worth mentioning:
- __import__() will raise ImportError instead of ValueError. In previous versions of Python, this would occur when a relative import went past its top-level package.
- The __file__ attribute of the __main__ module will be an absolute path instead of a relative path. This will be the case even if os.chdir() is used to change the current directory.
- Slight changes in the .replace() string method syntax are being introduced to address an edge case.
- Expanded decorator grammar: the number of valid expressions that can be used as decorators will be much larger than in previous versions of Python.
- New modules including zoneinfo and graphlib:
- Zoneinfo introduces the IANA time zone database to the Python standard library.
- Graphlib provides support for graph-like objects in Python.
There’s a host of other changes you can read about, but they likely won’t have a big effect on the majority of Python users.
Summary
Python 3.9 incorporates a number of changes that improve support for features that have in the past required either third party libraries to do the heavy lifting, or else the implementation of some pretty cumbersome code. For example, working with time zones will no longer require packages like dateutil, working with type hints no longer requires the import of the list type, and merging dictionaries is now far simpler.
But Python 3.9 also pushes forward Python’s flexibility by introducing a new parser with fewer limitations and the ability to define literally anything as a decorator.
One last thing to note is a change in release cadence. Traditionally, new Python versions have been released every 18 months or so, but that is now changing to every 12 months. While a yearly cycle does mean we’ll see fewer features in each release, at least we’ll get to use those features sooner.
For more information on all the updates in Python 3.9, refer to the official changes posted on the Python 3.9 docs page.
Why Download Python 3.9 From ActiveState?
Because with ActiveState, you can build a custom Python, tailored to your needs.
ActiveState’s platform makes it possible to automate your build engineering cycle, dependency management and check for threats and license compliance.
- Pick only the packages you need
- We automatically resolve all dependencies
- You get an easy-to-deploy runtime environment