Live data from Hacker News

Don't let dicts spoil your code

roman.pt

31–40 of 121 posts

Re: Don't let dicts spoil your code

#31
post #21

Earlier quoted context omitted.

> Python doesn't do typing well Golang does typing, but JSONs are PITA to handle. Try parsing something like `[{"a': 1, "b": "c", "d": [], "e": {}}, null, 1, "2"]` in go. Types are a bless as well as a curse.

Thats only because your list has different types. Its a badly formed API and if you really need to support that use case then you can use maps and reflection to handle it.

The problem is, programmers can't dictate what JSON should look like in the wild.

We used to have strict typed XML. Nobody even bothered.

Re: Don't let dicts spoil your code

#32
I've cleaned up code where input parameters came in a dict form. Absolute shit show.

- The only way to figure out which parameters are even possible was to search through the code for the uses of the dict.

- Default values were decided on the spot all over the place (input.getOrDefault(..)).

- Parameter names had to be typed out each time, so better be careful with correct spelling.

- Having a concise overview how the input is handled (sanitized) was practically impossible.

0/10 design decision, would not recommend.

Re: Don't let dicts spoil your code

#34

Here’s an out-there take, but one I’ve held loosely for a long time and haven’t shed yet: dicts are not appropriate for what people mostly use them for, which is named access to member attributes. dict is an implementation of a hash table. Hash table are designed for o(1) lookup of items. As such, they are arrays which are much bigger than the number of items they store, to allow hashing items into integers and sides…

Dicts in python are for when you have a thing and you aren't sure what the keys are. Dataclasses are for when you have a thing and you're sure what the keys (attributes are). The trouble is when you have a thing and you're sort of sure, but not entirely sure, and some things are definitely there but not everything you might be thinking of.

Re: Don't let dicts spoil your code

#35
post #22

dicts are OK, because at least they do have a `key` and it does mean something. un-annotated tuples and too many func params are cancer.

No no, Un-annotated tuples and too many func params are OK, because at least they are pushed and popped from the stack. Calls and rets without a prologue and epilogue on the other hand…

[deleted]

Re: Don't let dicts spoil your code

#36
Dicts can be a problem, but this particular example isn't that great, like in this diagram from the article:

  External API  Ser/De  Business Logic
Life's all great until "External API" adds a field that your model doesn't know about, it gets dropped when you deserialize it, and then when you send it back (or around somewhere else) it's missing a field.

There's config for this in Pydantic, but it's not the default, and isn't for most ser/de frameworks (TypeScript is a notable exception here).

Closed enums have a similar tradeoff.

Re: Don't let dicts spoil your code

#37

Earlier quoted context omitted.

TypedDicts solve the linting problem, but refactoring tools haven't caught up (unlike e.g. ForwardRef type annotations, which are strings but can be transformed alongside type literals).

Is there any advantage to using a TypedDict for a record over a dataclass?

TypedDicts "aren't real" in the sense that they're a compile-time feature, so you're getting typing without any deserialization cost beyond the original JSON. Dataclasses and Pydantic models are slow to construct, so that's not nothing.

This of course means TypeDicts don't give you run-time validation. For that, and for full-blown custom types in general, I tend to favor msgspec Structs: https://jcristharif.com/msgspec/benchmarks.html#json-seriali....

Re: Don't let dicts spoil your code

#39

Here’s an out-there take, but one I’ve held loosely for a long time and haven’t shed yet: dicts are not appropriate for what people mostly use them for, which is named access to member attributes. dict is an implementation of a hash table. Hash table are designed for o(1) lookup of items. As such, they are arrays which are much bigger than the number of items they store, to allow hashing items into integers and sides…

Subclassing NamedTuple is very ergonomic, and given they're immutable unlike data classes I often reach for them by default. I still use Pydantic when I want custom validation or when it ties into another lib like FastAPI.

Re: Don't let dicts spoil your code

#40

For better or for worse, Python doesn't do typing well. I don't disagree that I prefer well defined types, but if that is your desire then I think Python is perhaps not the correct choice of language.

Personnaly I became a huge fan of beartype : https://pypi.org/project/beartype/ Leyec, the magic dev behind it managed to make a full python type checker with super advanced features and about 0 overhead. It's crazy

I tried using it, but beartype quickly became a pain with having to decorate things manually. Then I found typeguard which goes even further and never looked back. Instead of manually decorating each individual function, an import hook can be activated that automatically decorates any function with type annotation. Massive QoL improvement. I have it set to only activate during testing though as I'm unsure of the overhead.
Post reply on HN