Python 3.9 Features That Will Make Your Life Easier

Python 3.9 Features That Will Make Your Life Easier Featured Image

Every time Python comes out with a new version, I like to jump right in and start using the latest features—especially if they make my life easier. Well, Python 3.9 did not disappoint, and there are three new features I want to talk about today: the union operator, type hinting generics, and a pair of new string methods. Let’s dive in!

Table of Contents

Python 3.9 Overview

I wouldn’t exactly consider myself obsessed with Python, but I really love the language and everything the dev team does to keep it feeling fresh and new. In this latest installment of the language as of October 5th, 2020, we’re graced with 7 brand new features according to PEP 596Opens in a new tab.:

  • PEP 584Opens in a new tab., Add Union Operators To dict
  • PEP 585Opens in a new tab., Type Hinting Generics In Standard Collections
  • PEP 593Opens in a new tab., Flexible function and variable annotations
  • PEP 614Opens in a new tab., Relaxing Grammar Restrictions On Decorators
  • PEP 615Opens in a new tab., Support for the IANA Time Zone Database in the Standard Library
  • PEP 616Opens in a new tab., String methods to remove prefixes and suffixes
  • PEP 617Opens in a new tab., New PEG parser for CPython

While these are all great features, I’m obviously very biased in that I’m most excited by any feature that simplifies a task for me. After all, that’s what drew me into Python in the first place: I want to be able to move from concept to code as quickly as possible. Well, this latest round of updates didn’t disappoint! Let’s talk about it.

Python 3.9 Features

As a quick heads up, we’re going to be talking about three features from the list above:

  • The Dictionary Union Operator
  • Type Hinting Generics in Standard Collections
  • String Methods to Remove Prefixes and Suffixes

While I’m sure all seven features are excellent, these three really caught my eye, so I wanted to focus on them. If you’re interested in hearing my opinion on the other four features, let me know!

Dictionary Union Operator

As many of you know, the one The Renegade Coder series that really brings in the views is my How to Python series. In it, I write about everyday problems and how to solve them. If you’re looking for a good place to start, here’s a nice list post.

At any rate, back in the summer of 2019, I wrote about how annoying it was to merge dictionaries. At the time, these were the best solutions:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

# Dictionary Comprehension
powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}

# Dictionary unpacking (Python 3.5+)
powers = {**yusuke_power, **hiei_power}

All of this just so we can get the following dictionary:

powers = {
  "Yusuke Urameshi": "Spirit Gun",
  "Hiei": "Jagan Eye"
}

Oddly enough, this article gets cited quite a bit in the community (e.g. in this MiniScript forumOpens in a new tab.) because it shows a major gap in language design. Surely, merging dictionaries should be easier.

Well, in late 2020, we finally have an option: the dictionary union operator. It’s a simple change, but basically it allows us to reduce the code from above down to something like this:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = yusuke_power | hiei_power

In this case, the new operator (|) is doing all the heavy lifting. But wait, it gets better! If you want to merge dictionaries directly without generating a new dictionary, you can use the augmented union operator:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
yusuke_power |= hiei_power

In this case, yusuke_power would store the result of the union. How cool is that?

As you can probably imagine, I updated my dictionary merging article a few months back when I heard about this feature. I can’t tell you how excited I am to see it in the official language.

Type Hinting Generics In Standard Collections

While the dictionary union operator is nice, it has a very niche use, and I don’t suspect I’ll be using it very often. On the other hand, type hinting is something that I think is really starting to catch on with the popularity of TypeScript. Personally, I’ve been using type hinting for awhile (see image-titlerOpens in a new tab.), so any improvements to the process would be welcomed.

Well, apparently, people have been complaining that it’s sort of annoying to write out type hints for generic types like lists. For example, prior to Python 3.9, if you wanted to specify that a function returned a list of strings, you’d have to do something like this (source image-titlerOpens in a new tab.):

def process_images(**kwargs) -> List[Image.Image]:
    """
    The main entry point for any image editing. This function
    will never return an empty list. If no settings are provided,
    this function will return a default image with a default title.
    :return: None
    """
    is_batch: bool = kwargs.get(KEY_BATCH)
    images = list()
    if is_batch:
        kwargs[KEY_PATH] = kwargs.get(KEY_PATH) if kwargs.get(KEY_PATH) else TRC_IMAGES
        images = _process_batch(**kwargs)
    else:
        kwargs[KEY_PATH] = kwargs.get(KEY_PATH) if kwargs.get(KEY_PATH) else TRC_IMAGE
        kwargs[KEY_TITLE] = kwargs.get(KEY_TITLE) if kwargs.get(KEY_TITLE) else _convert_file_name_to_title(**kwargs)
        images.append(_process_image(**kwargs))
    return images

Which unfortunately requires a special import:

from typing import List

Now, having used this typing library for awhile, I wasn’t really bothered by this. That said, I can totally understand why new folks would be annoyed. In fact, the rationale for the feature that simplifies this states:

This change removes the necessity for a parallel type hierarchy in the typing module, making it easier for users to annotate their programs and easier for teachers to teach Python.

Heck, I’m a teacher! So, I’m totally onboard. That said, what exactly did they change? Well, Python 3.9 now lets us type hint standard collections exactly as they appear normally. In other words, instead of using List, we can use list directly. Here’s what that would look like:

def process_images(**kwargs) -> list[Image.Image]:
    """
    The main entry point for any image editing. This function
    will never return an empty list. If no settings are provided,
    this function will return a default image with a default title.
    :return: None
    """
    is_batch: bool = kwargs.get(KEY_BATCH)
    images = list()
    if is_batch:
        kwargs[KEY_PATH] = kwargs.get(KEY_PATH) if kwargs.get(KEY_PATH) else TRC_IMAGES
        images = _process_batch(**kwargs)
    else:
        kwargs[KEY_PATH] = kwargs.get(KEY_PATH) if kwargs.get(KEY_PATH) else TRC_IMAGE
        kwargs[KEY_TITLE] = kwargs.get(KEY_TITLE) if kwargs.get(KEY_TITLE) else _convert_file_name_to_title(**kwargs)
        images.append(_process_image(**kwargs))
    return images

It’s subtle, but this change is amazing. Not only do we not need to import a special library, but we also don’t need to try to remember which casing to use for our collections (e.g. ‘list’ vs. ‘List’).

There’s no doubt I’ll be revisiting projects to take advantage of this feature. Maybe I’ll take a quick pass over all the code snippets in the Python section of the Sample Programs repoOpens in a new tab.. Who knows!

String Methods to Remove Prefixes and Suffixes

Finally, the last feature I want to talk about today is the addition of two new methods to the string class. Apparently, a lot of folks had been using the lstrip() and rstrip() methods of string to remove prefixes and suffixes, respectively. In particular, they had assumed that the input was a substring when it was actually a character set which caused a lot of bugs.

As a result, the dev team felt it would be appropriate to provide the behavior that folks were expecting through two new methods:

  • removeprefix()
  • removesuffix()

These methods accept a substring and remove it if it exists. Of course, strings are immutable, so these methods return new strings. That said, I suspect it will relieve a ton of headache. I’m really excited to see where this will be used in real world contexts.

Looking Ahead to Python 3.10

With Python 3.9 officially out the door, it’ll only be a year before 3.10 rolls out. If you’re interested in what’s planned for the next version, check out PEP 619Opens in a new tab.. As far as I can tell, the dev team released the first alpha on the same day they released 3.9, so you can already test out the following feature: PEP 618—Add Option Length-Checking to ZipOpens in a new tab..

Like I said, the Python team does a great job of keeping their language fresh and new. Also, it’s nice to know that the team is looking to help developers out by including features that make out lives easier.

That said, I think it’s helpful to be critical of any new features. For instance, I once raised some concerns about the walrus operator in Python 3.8. I think the last thing we want is a language that’s hard to read and maintain.

Overall, I’m quite pleased with Python 3.9, and I’m excited to see how Python 3.10 shapes up. In the meantime, I’ll keep writing solutions to everyday problems! If you’re looking for somewhere to start, check out these articles:

Likewise, you can help me grow this site by visiting this list where you’ll find links to our community Discord, my YouTube channel, and the newsletter.

In addition, here are some resources from Amazon to help you learn Python (#ad):

Thanks again for check out the site! I appreciate it. Take care.

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Then, he earned a master's in Computer Science and Engineering. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife and kid, playing Overwatch 2, Lethal Company, and Baldur's Gate 3, reading manga, watching Penguins hockey, and traveling the world.

Recent Code Posts