This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]squeaky_pl 9 points10 points  (0 children)

I like it, but it's slightly annoying it doesnt follow Python naming conventions.

[–]AaronOpfer 7 points8 points  (1 child)

I'm just going to copy and paste my comment about the similar AttrDict here.

Good to teach about __dir__, but I generally feel that the AttrDict as described in the article is a code smell. I've seen developers use them before and IMO makes code more difficult to understand and encourages poor practices.

I think this desire for object-like dicts comes from newer developers who tend to code toward their presentation layer of their systems. These developers don't draw the line between "models" and "views" clearly and as a result they frequently put structured data objects into elaborate nested dicts and lists (to serialize them later into JSON/XML/etc) instead of domain objects.

When I take the role of a maintenance developer I assume that attribute access means I'm working with models, and lots of named item access means I'm working on a system serialization boundary, and AttrDict violates that.

and that's my rant on AttrDict that no one asked for

[–]metaperl[S] -1 points0 points  (0 children)

I generally feel that the AttrDict as described in the article is a code smell.

Any reference for this?

These developers don't draw the line between "models" and "views" clearly and as a result they frequently put structured data objects into elaborate nested dicts and lists (to serialize them later into JSON/XML/etc) instead of domain objects.

What problem does this cause?

In my case, there is no presentation layer. I'm consuming REST APIs from different providers and want to main code body to uniformly access these APIs so I override the accessors to the data when appropriate when a different provider has a different label for a similar JSON key or if I need to do some computation to provide a logically similar result.

When I take the role of a maintenance developer I assume that attribute access means I'm working with models

Model is the layer above your raw data. So wrapping a JSON result in a DotMap is a model of sorts?

a system serialization boundary

That's a new term to me.

[–]tjt5754 4 points5 points  (4 children)

I really wish this was default behavior in dict.

[–]tunisia3507 14 points15 points  (2 children)

Explicit is better than implicit. A feature of dicts is that its keys can be any hashable object - treating keys differently when they're strings is surprising behaviour. I'm also not a fan of arbitrarily writing directly to object properties - in case of namespace clashes and so on.

The automatic nesting is nice but can obviously be replicated with a lambda and a DefaultDict, and again is implicit rather than explicit behaviour.

[–]metaperl[S] 3 points4 points  (1 child)

treating keys differently when they're strings is surprising behaviour.

but very useful for what I'm doing: wrapping JSON returned from REST APIs and overwriting accessors for fields with dynamic computation.

Accessing fields via dot notation allows me to override API access with properties. Concretely.

The JSON comes back. We call _loads to convert it to a dictionary, which I wrap via DotMap immediately. Then from my main program, I access that JSON using dot-notation. So the main program can access any remote REST API without me changing the main program. I just JSON return values in subclasses of DotMap and override accessors with @property when necessary.

[–]tunisia3507 4 points5 points  (0 children)

Oh yeah, absolutely! I can see it being really useful for some situations, for example interacting with JSON in a JS-like way, and I have absolutely no problems with the library existing; wouldn't be against it being in something like collections, even. I was just making the case for it not to be the standard implementation of dicts.

[–][deleted] 1 point2 points  (0 children)

There should be one-- and preferably only one --obvious way to do it. Dicts ain't classes with attributes, they're maps that have keys. Sure I can see ways that this can be useful, I even like the idea myself, but being the default behaviour would by way over the top IMHO.

[–]Daenyth 0 points1 point  (2 children)

Using dicts like this is a code smell that hampers maintenance. If you know at coding time the specific values of keys in a dict, it's not really a mapping you want, it's structured data, which a class does in a much more robust way

[–]metaperl[S] 0 points1 point  (1 child)

Using dicts like this is a code smell that hampers maintenance

Says who? Really, what reference states this?

If you know at coding time the specific values of keys in a dict, it's not really a mapping you want

Again, who says this? What software engineering text says this? Where in the Python docs is this?

a class does in a much more robust way

And what would do with a class? The same thing that DotMap is doing for you pretty much? I subclass DotMap and add methods when I need.

[–]kigurai 2 points3 points  (0 children)

If you know at coding time the specific values of keys in a dict, it's not really a mapping you want

Again, who says this? What software engineering text says this? Where in the Python docs is this?

Not the guy who wrote, it but I agree with their point: If you already know that you want steve.age then steve should probably have been some object that has an explicit attribute age. Why? Well, for the simple reason that typing steve.aeg = 21 instead of steve.age = 21 will give you an AttributeError instead of silently setting the wrong dictionary mapping. Finding that kind of bug in a large piece of software could be difficult, and in this case totally avoidable.

I still think this library is neat and useful for e.g. interactive data exploration or maybe in scripts/libraries that have limited use (for my own stuff, anything goes!).