Accessing dict keys like an attribute?

前端 未结 27 2106
南笙
南笙 2020-11-22 04:22

I find it more convenient to access dict keys as obj.foo instead of obj[\'foo\'], so I wrote this snippet:

class AttributeDict(dict         


        
相关标签:
27条回答
  • 2020-11-22 05:07

    Apparently there is now a library for this - https://pypi.python.org/pypi/attrdict - which implements this exact functionality plus recursive merging and json loading. Might be worth a look.

    0 讨论(0)
  • 2020-11-22 05:07

    Solution is:

    DICT_RESERVED_KEYS = vars(dict).keys()
    
    
    class SmartDict(dict):
        """
        A Dict which is accessible via attribute dot notation
        """
        def __init__(self, *args, **kwargs):
            """
            :param args: multiple dicts ({}, {}, ..)
            :param kwargs: arbitrary keys='value'
    
            If ``keyerror=False`` is passed then not found attributes will
            always return None.
            """
            super(SmartDict, self).__init__()
            self['__keyerror'] = kwargs.pop('keyerror', True)
            [self.update(arg) for arg in args if isinstance(arg, dict)]
            self.update(kwargs)
    
        def __getattr__(self, attr):
            if attr not in DICT_RESERVED_KEYS:
                if self['__keyerror']:
                    return self[attr]
                else:
                    return self.get(attr)
            return getattr(self, attr)
    
        def __setattr__(self, key, value):
            if key in DICT_RESERVED_KEYS:
                raise AttributeError("You cannot set a reserved name as attribute")
            self.__setitem__(key, value)
    
        def __copy__(self):
            return self.__class__(self)
    
        def copy(self):
            return self.__copy__()
    
    0 讨论(0)
  • 2020-11-22 05:08

    It doesn't work in generality. Not all valid dict keys make addressable attributes ("the key"). So, you'll need to be careful.

    Python objects are all basically dictionaries. So I doubt there is much performance or other penalty.

    0 讨论(0)
  • 2020-11-22 05:08

    This is what I use

    args = {
            'batch_size': 32,
            'workers': 4,
            'train_dir': 'train',
            'val_dir': 'val',
            'lr': 1e-3,
            'momentum': 0.9,
            'weight_decay': 1e-4
        }
    args = namedtuple('Args', ' '.join(list(args.keys())))(**args)
    
    print (args.lr)
    
    0 讨论(0)
  • 2020-11-22 05:09

    You can pull a convenient container class from the standard library:

    from argparse import Namespace
    

    to avoid having to copy around code bits. No standard dictionary access, but easy to get one back if you really want it. The code in argparse is simple,

    class Namespace(_AttributeHolder):
        """Simple object for storing attributes.
    
        Implements equality by attribute names and values, and provides a simple
        string representation.
        """
    
        def __init__(self, **kwargs):
            for name in kwargs:
                setattr(self, name, kwargs[name])
    
        __hash__ = None
    
        def __eq__(self, other):
            return vars(self) == vars(other)
    
        def __ne__(self, other):
            return not (self == other)
    
        def __contains__(self, key):
            return key in self.__dict__
    
    0 讨论(0)
  • 2020-11-22 05:10

    tuples can be used dict keys. How would you access tuple in your construct?

    Also, namedtuple is a convenient structure which can provide values via the attribute access.

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