Live data from Hacker News

A “frozen” dictionary for Python

lwn.net

51–60 of 172 posts

Re: A “frozen” dictionary for Python

#51
post #20

I wonder whether Raymond Hettinger has an opinion on this PEP. A long time ago, he wrote: "freezing dicts is a can of worms and not especially useful". https://mail.python.org/pipermail/python-dev/2006-February/0...

This was 19 (almost) 20 years ago. As stated in the lwn.net article, a lot of concurrency has been added to python, and it might now be time for something like a frozendict. Things that were not useful in 2006 might be totally useful in 2026 ;P Still, like you, I'm curious wether he has anything to say about it.

I think Raymond Hettinger is called out specially here because he did a well known talk called [Modern Dictionaries](https://youtu.be/p33CVV29OG8) where around 32:00 to 35:00 in he makes the quip about how younger developers think they need new data structures to handle new problems, but eventually just end up recreating / rediscovering solutions from the 1960s.

“What has been is what will be, and what has been done is what will be done; there is nothing new under the sun.”

Re: A “frozen” dictionary for Python

#52
post #27

Earlier quoted context omitted.

Aren’t sets unsorted by definition? Or do repeated accesses without modification yield different results?

So are dictionary keys, but Python decided to make them insertion ordered (after having them be unordered just like set elements for decades). There is no fundamental reason sets couldn't have a defined order. That's what languages like JavaScript have done too.

Python's decision to make dict keys ordered in the spec was a mistake. It may be the best implementation so far, but it eliminates potential improvements in the future.

Re: A “frozen” dictionary for Python

#53
post #26

Earlier quoted context omitted.

The values in tuples cannot change. The values that keys point to in a frozen dict can? But yeah I'd be in favour of something that looked a lot like a named tuple but with mutable values and supporting [name] access too. And of course some nice syntactic sugar rather like dicts and sets have with curly brackets today.

> The values in tuples cannot change. The values that keys point to in a frozen dict can? The entries of a tuple cannot be assigned to, but the values can be mutated. The same is true for a `frozendict` (according to the PEP they don't support `__setitem__`, but "values can be mutable").

Tuple entries must be hashable, which (as far as standard library is concerned) means immutable.

Re: A “frozen” dictionary for Python

#54
post #26

Earlier quoted context omitted.

> The values in tuples cannot change. The values that keys point to in a frozen dict can? The entries of a tuple cannot be assigned to, but the values can be mutated. The same is true for a `frozendict` (according to the PEP they don't support `__setitem__`, but "values can be mutable").

Tuple entries must be hashable, which (as far as standard library is concerned) means immutable.

  >>> hash([1, 2])
  TypeError: unhashable type: 'list'

  >>> t = ([1, 2], [3, 4])
  >>> print(t)
  ([1, 2], [3, 4])

Re: A “frozen” dictionary for Python

#55
post #46

This subject always seems to get bogged down in discussions about ordered vs. unordered keys, which to me seems totally irrelevant. No-one seems to mention the glaring shortcoming which is that, since dictionary keys are required to be hashable, Python has the bizarre situation where dicts cannot be dict keys, as in... {{'foo': 'bar'}: 1, {3:4, 5:6}: 7} ...and there is no reasonable builtin way to get around this! Yo…

Turning a dictionary into a tuple of tuples `((k1, v1), (k2, v2), ...)`; isn't that a reasonable way?

If you want to have hash map keys, you need to think about how to hash them and how to compare for equality, it's just that. There will be complications to that such as floats, which have a tricky notion of equality, or in Python mutable collections which don't want to be hashable.

Re: A “frozen” dictionary for Python

#56
post #41
post #30

Wow weird Mandela effect for me. I really remember this being a built and actually using it.

You may be thinking of the `frozenset()` built in or the third party Python module [frozendict]( https://pypi.org/project/frozendict/ )? Personally, I’ve been using a wrapper around `collections.namedtuple` as an underlying data structure to create frozen dictionaries when I’ve needed something like that for a project.

When you are making str -> Any dictionaries it's quite likely you're better off with dataclasses or namedtuples anyway.

Re: A “frozen” dictionary for Python

#57
post #50
post #39

Earlier quoted context omitted.

> Another PEP 351 world view is that tuples can serve as frozenlists; however, that view represents a Liskov violation (tuples don't support the same methods). This idea resurfaces and has be shot down again every few months. ... Well, yes; it doesn't support the methods for mutation . Thinking of ImmutableFoo as a subclass of Foo is never going to work. And, indeed, `set` and `frozenset` don't have an inheritance re…

> ImmutableFoo as a subclass of Foo is never going to work. And, indeed, `set` and `frozenset` don't have an inheritance relationship. Theoretically, could `set` be a subclass of `frozenset` (and `dict` of `frozendict`)? Do other languages take that approach? > linking [immutability] more explicitly to hashability AFAIK immutability and hashability are equivalent for the language's "core" types. Would it be possible…

> Theoretically, could `set` be a subclass of `frozenset` (and `dict` of `frozendict`)?

At one extreme: sure, anything can be made a subclass of anything else, if we wanted to.

At the other extreme: no, since Liskov substitution is an impossibly-high bar to reach; especially in a language that's as dynamic/loose as Python. For example, consider an expression like '"pop" in dir(mySet)'

Re: A “frozen” dictionary for Python

#58
post #40

Earlier quoted context omitted.

That's a great link and recommended reading. It explains a lot about the design of Python container classes, and the boundaries of polymorphism / duck typing with them, and mutation between them. I don't always agree with the choices made in Python's container APIs...but I always want to understand them as well as possible. Also worth noting that understanding changes over time. Remember when GvR and the rest of the…

> Also worth noting that understanding changes over time. Remember when GvR and the rest of the core developers argued adamantly against ordered dictionaries? Haha! Good times! The new implementation has saved space, but there are opportunities to save more space (specifically after deleting keys) that they've now denied themselves by offering the ordering guarantee.

Ordering, like stability in sorting, is an incredibly useful property. If it costs a little, then so be it.

This is optimizing for the common case, where memory is generally plentiful and dicts grow more than they shrink. Python has so many memory inefficiencies that occasional tombstones in the dict internal structure is unlikely to be a major effect. If you're really concerned, do `d = dict(d)` after aggressive deletion.

Re: A “frozen” dictionary for Python

#59
post #42
post #6

A frozen dictionary would be very welcome. You can already do something similar using MappingProxyType [0] from types import MappingProxyType d = {} d["a"] = 1 d["b"] = 2 print(d) frozen = MappingProxyType(d) print(frozen["a"]) # Error: frozen["b"] = "new" [0]: https://docs.python.org/3/library/types.html#types.MappingPr...

> You can already do something similar Only if you deny access to the underlying real dict.

Yes, this only prevents the callee from mutating it, it can't provide a strong guarantee that the underlying mapping won't be changed upstream (and hence MappingProxyType can't be washable).

Re: A “frozen” dictionary for Python

#60
post #54

Earlier quoted context omitted.

Tuple entries must be hashable, which (as far as standard library is concerned) means immutable.

>>> hash([1, 2]) TypeError: unhashable type: 'list' >>> t = ([1, 2], [3, 4]) >>> print(t) ([1, 2], [3, 4])

Ah. Of course… that’s how the workaround to use tuples as frozen dicts can work in the first place. Slow morning for me!
Post reply on HN