Tech News
← Back to articles

A “frozen” dictionary for Python

read original related products more articles

A "frozen" dictionary for Python [LWN subscriber-only content]

Welcome to LWN.net The following subscription-only content has been made available to you by an LWN subscriber. Thousands of subscribers depend on LWN for the best news from the Linux and free software communities. If you enjoy this article, please consider subscribing to LWN. Thank you for visiting LWN.net!

Dictionaries are ubiquitous in Python code; they are the data structure of choice for a wide variety of tasks. But dictionaries are mutable, which makes them problematic for sharing data in concurrent code. Python has added various concurrency features to the language over the last decade or so—async, free threading without the global interpreter lock (GIL), and independent subinterpreters—but users must work out their own solution for an immutable dictionary that can be safely shared by concurrent code. There are existing modules that could be used, but a recent proposal, PEP 814 ("Add frozendict built-in type"), looks to bring the feature to the language itself.

Victor Stinner announced the PEP that he and Donghee Na have authored in a post to the PEPs category of the Python discussion forum on November 13. The idea has come up before, including in PEP 416, which has essentially the same title as 814 and was authored by Stinner back in 2012. It was rejected by Guido van Rossum at the time, in part due to its target: a Python sandbox that never really panned out.

frozendict

The idea is fairly straightforward: add frozendict as a new immutable type to the language's builtins module. As Stinner put it:

We expect frozendict to be safe by design, as it prevents any unintended modifications. This addition benefits not only CPython's standard library, but also third-party maintainers who can take advantage of a reliable, immutable dictionary type.

While frozendict has a lot in common with the dict built-in type, it is not a subclass of dict ; instead, it is a subclass of the base object type. The frozendict() constructor can be used to create one in various ways:

fd = frozendict() # empty fd = frozendict(a=1, b=2) # frozen { 'a' : 1, 'b' : 2 } d = { 'a' : 1, 'b' : 2 } fd = frozendict(d) # same l = [ ( 'a', 1 ), ( 'b', 2 ) ] fd = frozendict(l) # same fd2 = frozendict(fd) # same assert d == fd == fd2 # True

As with dictionaries, the keys for a frozendict must be immutable, thus hashable, but the values may or may not be. For example, a list is a legitimate type for a value in either type of dictionary, but it is mutable, making the dictionary as a whole (frozen or not) mutable. However, if all of the values stored in a frozendict are immutable, it is also immutable, so it can be hashed and used in places where that is required (e.g. dictionary keys, set elements, or entries in a functools.lru_cache ).

... continue reading