Javascript style dot notation for dictionary keys unpythonic?

前端 未结 12 991
刺人心
刺人心 2020-12-23 10:44

I\'ve started to use constructs like these:

class DictObj(object):
    def __init__(self):
        self.d = {}
    def __getattr__(self, m):
        return s         


        
相关标签:
12条回答
  • 2020-12-23 10:47

    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
    >>> 
    
    0 讨论(0)
  • 2020-12-23 10:48

    There's a symmetry between this and this answer:

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

    The same interface, just implemented the other way round...

    class container(object):
        __getitem__ = object.__getattribute__
        __setitem__ = object.__setattr__
        __delitem__ = object.__delattr__
    
    0 讨论(0)
  • 2020-12-23 10:55

    It's not "wrong" to do this, and it can be nicer if your dictionaries have a strong possibility of turning into objects at some point, but be wary of the reasons for having bracket access in the first place:

    1. Dot access can't use keywords as keys.
    2. Dot access has to use Python-identifier-valid characters in the keys.
    3. Dictionaries can hold any hashable element -- not just strings.

    Also keep in mind you can always make your objects access like dictionaries if you decide to switch to objects later on.

    For a case like this I would default to the "readability counts" mantra: presumably other Python programmers will be reading your code and they probably won't be expecting dictionary/object hybrids everywhere. If it's a good design decision for a particular situation, use it, but I wouldn't use it without necessity to do so.

    0 讨论(0)
  • 2020-12-23 10:56

    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?

    0 讨论(0)
  • 2020-12-23 10:56

    The one major disadvantage of using something like your DictObj is you either have to limit allowable keys or you can't have methods on your DictObj such as .keys(), .values(), .items(), etc.

    0 讨论(0)
  • 2020-12-23 11:00

    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.

    0 讨论(0)
提交回复
热议问题