Following hot on the heels of PostgreSQL 13, my other favourite development software was updated last week. As of October 5th, 2020, Python 3.9 has been released into the wild, and it brings a slew of new features and improvements.
A lot of these are enhancements to the underlying Python library code/implementation that is not “user facing”. This post will just talk about a few upgrades that I think are generally the most useful, ones that your code will actually be able to touch directly. Let’s jump right in.
Dictionary union operators
Python 3.9 implements PEP584, which adds union operators to dictionaries. What does this mean? In practical terms, the process to combine two dictionaries together has become simpler.
In previous Python versions, the update
method could be used to combine two dictionaries, like so:
>>> d = {"a": 1, "b": 2, "c": 3}
>>> d.update({"c": 4, "d": 5})
>>> d
{'a': 1, 'b': 2, 'c': 4, 'd': 5}
What happens here is that the dictionary (d
in our example) is updated in place. Keys in the dictionary being passed to update
overwrite those that already exist in d
, as opposed to being merged into a new, non-d
dictionary.
This works fine – provided you’re happy with updating the dictionary in such a forceful way. Before now, there was no concise, one-line method to combine two dictionaries into a new and unified dictionary.
The union operator (|
) provides a solution. In the first instance, we’ll see how it’s used to combine two dictionaries into a new one.
>>> d = {"a": 1, "b": 2, "c": 3}
>>> e = d | {"c": 4, "d": 5}
>>> e
{'a': 1, 'b': 2, 'c': 4, 'd': 5}
>>> d
{'a': 1, 'b': 2, 'c': 3} # d is unchanged
The operator can also be used as an augmented assignment (|=
) to replace update
in our previous example.
>>> d = {"a": 1, "b": 2, "c": 3}
>>> d |= {"c": 4, "d": 5}
>>> d
{'a': 1, 'b': 2, 'c': 4, 'd': 5}
It’s hardly a groundbreaking addition to Python, but it’s a nice-to-have feature that should help make programs more concise and just that little bit faster to compile.
Built-in string prefix/suffix removal
Another nice little feature is the addition of the removeprefix
and removesuffix
methods to the str
class.
These will return a copy of the target string, with the given prefix/suffix removed, if it exists. If the prefix/suffix is not present on the string, then the entire string is returned.
Here’s a short example:
>>> s = "test_string"
>>> s.removeprefix("bad-prefix")
'test_string'
>>> s.removeprefix("test_")
'string'
>>> s
'test_string'
The removesuffix
method behaves similarly; it returns a string value for a variable with a matching suffix removed.
These methods make for another simple addition, but using them should let programmers cut down on code for the common pattern of having to first check if a prefix/suffix exists before attempting to remove it from the string.
Timezone data is now built-in
Since Python 3.2, the datetime.timezone
class has provided an abstract base interface to implement timezones for datetime.datetime
objects. For reasons that I’ve never understood (actually, reasons I’ve never bothered to investigate), Python hasn’t included any timezone data in its standard library before now.
This has changed with PEP615 in Python 3.9. This introduces the zoneinfo
module, which includes IANA timezone support.
In short, ZoneInfo
classes can be constructed with timezone names to create an instance of the timezone information. For example:
from zoneinfo import ZoneInfo
zone = ZoneInfo("America/Los_Angeles")
This is similar to the tz
module of dateutil
which needed to be used in previous Python versions.
While it’s never been too difficult to add dateutil
or some other timezone package to your package requirements, having one less dependency to manage is always welcome.
When can I start using it?
Right now!
Well, of course we know that’s only technically true. Of course you can download Python 3.9 from the usual place right now.
For macOS users, Python 3.9 available in HomeBrew now. My guess is that it will be available for CentOS in a few months, and an official release will soon make its way to Ubuntu 21.04. It can be downloaded from third party repositories now, though.
However, all of the new features are somewhat of a moot point if Python 3.9 is not available in your deployment environment.
I don’t want to diverge too far from the subject of Python 3.9, but my (general) advice would be to try to keep up with the latest Python release as much as you can. This applies to other software you’re using too. It’s easier to go from version 3.9 to 3.10 than it is from 3.2 to 3.10. I could write (and sort of have written) a whole post on the importance of staying up-to-date with the latest developments in your area of expertise.
Conclusion
Python 3.9 brings a few nice features to help clean up your code base, reduce the number of lines of code and decrease external dependencies.
I wouldn’t say it’s a killer, must-have release, but I’d recommend jumping on it as soon as you can, if only to reduce friction for future upgrades.