Javascript style dot notation for dictionary keys unpythonic?

前端 未结 12 992
刺人心
刺人心 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 11:01

    It's not bad if it serves your purpose. "Practicality beats purity".

    I saw such approach elserwhere (eg. in Paver), so this can be considered common need (or desire).

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

    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.

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

    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.

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

    If you're looking for an alternative that handles nested dicts:

    Recursively transform a dict to instances of the desired class

    import json
    from collections import namedtuple
    
    
    class DictTransformer():
        @classmethod
        def constantize(self, d):
            return self.transform(d, klass=namedtuple, klassname='namedtuple')
    
        @classmethod
        def transform(self, d, klass, klassname):
            return self._from_json(self._to_json(d), klass=klass, klassname=klassname)
    
        @classmethod
        def _to_json(self, d, access_method='__dict__'):
            return json.dumps(d, default=lambda o: getattr(o, access_method, str(o)))
    
        @classmethod
        def _from_json(self, jsonstr, klass, klassname):
            return json.loads(jsonstr, object_hook=lambda d: klass(klassname, d.keys())(*d.values()))
    

    Ex:

    constants = {
      'A': {
        'B': {
          'C': 'D'
        }
      }
    }
    CONSTANTS = DictTransformer.transform(d, klass=namedtuple, klassname='namedtuple')
    CONSTANTS.A.B.C == 'D'
    

    Pros:

    • handles nested dicts
    • can potentially generate other classes
    • namedtuples provide immutability for constants

    Cons:

    • may not respond to .keys and .values if those are not provided on your klass (though you can sometimes mimic with ._fields and list(A.B.C))

    Thoughts?

    h/t to @hlzr for the original class idea

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

    Don't overlook Bunch.

    It is a child of dictionary and can import YAML or JSON, or convert any existing dictionary to a Bunch and vice-versa. Once "bunchify"'d, a dictionary gains dot notations without losing any other dictionary methods.

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

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

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