Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript style dot notation for dictionary keys unpythonic?

Tags:

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?

like image 883
Parand Avatar asked Oct 22 '08 00:10

Parand


2 Answers

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.

like image 87
bobince Avatar answered Oct 11 '22 02:10

bobince


With regards to the DictObj, would the following work for you? A blank class will allow you to arbitrarily add to or replace stuff in a container object.

class Container(object):     pass  >>> myContainer = Container() >>> myContainer.spam = "in a can" >>> myContainer.eggs = "in a shell" 

If you want to not throw an AttributeError when there is no attribute, what do you think about the following? Personally, I'd prefer to use a dict for clarity, or to use a try/except clause.

class QuietContainer(object):     def __getattr__(self, attribute):         try:             return object.__getattr__(self,attribute)         except AttributeError:             return None  >>> cont = QuietContainer() >>> print cont.me None 

Right?

like image 33
hlzr Avatar answered Oct 11 '22 03:10

hlzr