I think the best option for this, which is one listed in the article, is the dataclass. It's like a struct in C or Rust. It's ideal for structured data, which is, I believe, what a named tuple is intended for.
The annoyance of dataclasses, of course, is that they interact very awkwardly with immutability, which much of the Python ecosystem mandates (due to lacking value semantics).
Is there a situation where Python ever passes by value? Like you can sort of pretend for primitive types but I can't think of case where it's actually value.
Non-CPython implementations may pass by value as an optimization for certain immutable builtin types. This is visible to code using `is`.
(It's surprisingly difficult to implement a rigorous way to detect this vs compile-time constant evaluation though; note that identical objects of certain types are pooled already when generating/loading bytecode files. I don't think any current implementation is smart enough to optimize the following though)
$ python3 -c 'o = object(); print(id(o) is id(o))'
False
$ pypy3 -c 'o = object(); print(id(o) is id(o))'
True
$ jython -c 'o = object(); print(id(o) is id(o))'
True
Are you saying `o` is passed by value? I think this behavior is due to the return from `id()` being interned, or not. `id(o) == id(o)` will be true in all cases
By default, dataclasses can't be used as keys in a `dict`. You have to either use `frozen` (in which case the generated `__init__` becomes an abomination) or use `unsafe_hash` (in which case you have no guardrails).
In languages with value semantics, nothing about this problem even makes sense, since obviously a dict's key is taken by value if it needs to be stored.
--
Tuple behavior is sensible if you are familiar with discussion of reference semantics (though not as much as if you also support value semantics).
Still, at least we aren't Javascript where the question of using composite keys is answered with "screw you".