Javascript style dot notation for dictionary keys

2019-01-30 15:54发布

I've started to use constructs like these:

class DictObj(object):
    def __init__(self):
        self.d = {}
    def __getattr__(self, m):
        return self.d.get(m, None)
    def __setattr__(self, m, v):
        super.__setattr__(self, m, v)

Update: based on this thread, I've revised the DictObj implementation to:

class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

class AutoEnum(object):
    def __init__(self):
        self.counter = 0
        self.d = {}
    def __getattr__(self, c):
        if c not in self.d:
            self.d[c] = self.counter
            self.counter += 1        
        return self.d[c]

where DictObj is a dictionary that can be accessed via dot notation:

d = DictObj()
d.something = 'one'

I find it more aesthetically pleasing than d['something']. Note that accessing an undefined key returns None instead of raising an exception, which is also nice.

Update: Smashery makes a good point, which mhawke expands on for an easier solution. I'm wondering if there are any undesirable side effects of using dict instead of defining a new dictionary; if not, I like mhawke's solution a lot.

AutoEnum is an auto-incrementing Enum, used like this:

CMD = AutoEnum()

cmds = {
    "peek":  CMD.PEEK,
    "look":  CMD.PEEK,
    "help":  CMD.HELP,
    "poke":  CMD.POKE,
    "modify": CMD.POKE,
}

Both are working well for me, but I'm feeling unpythonic about them.

Are these in fact bad constructs?

11条回答
Melony?
2楼-- · 2019-01-30 16:10

I like dot notation a lot better than dictionary fields personally. The reason being that it makes autocompletion work a lot better.

查看更多
Rolldiameter
3楼-- · 2019-01-30 16:13

Because you ask for undesirable side-effects:

A disadvantage is that in visual editors like eclipse+pyDev, you will see many undefined variable errors on lines using the dot notation. Pydef will not be able to find such runtime "object" definitions. Whereas in the case of a normal dictionary, it knows that you are just getting a dictionary entry.

You would need to 1) ignore those errors and live with red crosses; 2) suppress those warnings on a line by line basis using #@UndefinedVariable or 3) disable undefined variable error entirely, causing you to miss real undefined variable definitions.

查看更多
看我几分像从前
4楼-- · 2019-01-30 16:15

This is a simpler version of your DictObj class:

class DictObj(object):
    def __getattr__(self, attr):
        return self.__dict__.get(attr)

>>> d = DictObj()
>>> d.something = 'one'
>>> print d.something
one
>>> print d.somethingelse
None
>>> 
查看更多
姐就是有狂的资本
5楼-- · 2019-01-30 16:21

Your DictObj example is actually quite common. Object-style dot-notation access can be a win if you are dealing with ‘things that resemble objects’, ie. they have fixed property names containing only characters valid in Python identifiers. Stuff like database rows or form submissions can be usefully stored in this kind of object, making code a little more readable without the excess of ['item access'].

The implementation is a bit limited - you don't get the nice constructor syntax of dict, len(), comparisons, 'in', iteration or nice reprs. You can of course implement those things yourself, but in the new-style-classes world you can get them for free by simply subclassing dict:

class AttrDict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

To get the default-to-None behaviour, simply subclass Python 2.5's collections.defaultdict class instead of dict.

查看更多
女痞
6楼-- · 2019-01-30 16:23

As far as I know, Python classes use dictionaries to store their attributes anyway (that's hidden from the programmer), so it looks to me that what you've done there is effectively emulate a Python class... using a python class.

查看更多
登录 后发表回答