holdenweb

Dictoinary accessible via attribute access

Aug 18th, 2019
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.97 KB | None | 0 0
  1. class ObjectDict(dict):
  2.     """
  3.    Makes a dictionary behave like an object, with attribute-style access.
  4.    """
  5.     sentinel = object()  # Unique instance that cannot be passed as an argument
  6.  
  7.     def __new__(cls, arg=sentinel):
  8.         """
  9.        This recursive dict subclass converts a dict into an ObjectDict,
  10.        which can use attribute access to retrieve and set keys.
  11.        Floats, ints, strings and existing ObjectDicts are simply
  12.        returned. Lists are transformed into lists of ObjectDicts.
  13.        The __init__ method will only be called for ObjectDicts,
  14.        since only then is the argument class is the same as the returned value.
  15.        When a dict is passed in, standard dict creation is called.
  16.        """
  17.         if arg is cls.sentinel:
  18.             return super().__new__()
  19.         elif isinstance(arg, (int, float, str, ObjectDict)):
  20.             return arg
  21.         elif isinstance(arg, list):
  22.             return list(ObjectDict(x) for x in arg)
  23.         elif isinstance(arg, dict):
  24.             return super().__new__(cls, arg)
  25.         else:
  26.             raise ValueError(f"{type(arg)} objects cannot be ObjectDicts")
  27.  
  28.     def __init__(self, arg=sentinel):
  29.         """
  30.        This method is only called after creation of a new ObjectDict
  31.        instance. The __init__ method actually initialises the values
  32.        in the underlying dict.
  33.        """
  34.         if type(arg) is ObjectDict:
  35.             return  # Assume existing ObjectDicts do not need re-initialising
  36.         if arg is self.sentinel:  # Called without args
  37.             arg = {}
  38.         for (k, v) in arg.items():
  39.             self[k] = ObjectDict(v)
  40.  
  41.  
  42.     def __getattr__(self, name: str):
  43.         try:
  44.             return self[name]
  45.         except KeyError:
  46.             raise AttributeError(name)
  47.  
  48.     def __setattr__(self, name, value):
  49.         value = ObjectDict(value)
  50.         super().__setitem__(name, value)
  51.  
  52.     def __dir__(self):
  53.         return sorted(self.keys)
Advertisement
Add Comment
Please, Sign In to add comment