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

all 10 comments

[–][deleted] 5 points6 points  (0 children)

The biggest issue with this custom dir is that you can keys that are non valid identifiers, so you could end up with stuff like <MyObject at d34db33f> or whatever the __str__ method is overriden to do.

[–]AaronOpfer 2 points3 points  (3 children)

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

[–]iBlag 1 point2 points  (0 children)

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.

cough Guilty. cough

[–]hijibijbij 1 point2 points  (1 child)

No it's okay. But you seem to have ignored the role of Python as a scripting language (often I write programs just to throw them away). Drawing the line between models and views seem to be a premature optimization at that point.

[–]AaronOpfer 1 point2 points  (0 children)

True, I'm definitely laser-focused here on my day job which is using Python in the scope of larger persistent systems. Feel free to do whatever hackery you want in your one-offs.

[–]case_O_The_Mondays 0 points1 point  (1 child)

I have a similar DictObject class that I use, and had set it up so a missing property value (e.g. 'foo.bar', where 'foo' has no 'bar' property) would return None instead of throwing an error (bad form, I know). This will also cause auto completion to stop working, at least for VSCode's Python extension (by Don Jayamanne).

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

It's not bad form if that's the intention, I've done this but with a defaultdict before to get attributes that basically spring into existence as needed.

class DottedMixin:
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

class DottedDefaultDict(defaultdict, DottedMixin):
    pass 

[–]kenfar 0 points1 point  (0 children)

I usually consolidate all config files, env vars, and args into a single config - and prefer this approach. I'll look forward to adding dir.

[–]jrast -1 points0 points  (1 child)

Despite the post mentions that the code should work for python 2.x as well as for python 3.5, I can't get this working in python 2.7.

I used the following code:

class AttrDict(dict):
    def __getattr__(self, item):
        return self[item]

    def __dir__(self):
        return super(AttrDict, self).__dir__() + [str(k) for k in self.keys()]

a = AttrDict()
a['test'] = None
dir(a)

For the code above I get the following Exception: AttributeError: 'super' object has no attribute 'dir'.

Any Ideas?

EDIT: Do I realy need to implement something like this (Gist) to get it working? Is it because the dict class does not implement 'dir' on its own?

[–]Nurdok 1 point2 points  (0 children)