This seems to work: from types import SimpleNamespace from collections.abc import Iterable
def isIterableNotStr(arg): return isinstance(arg, Iterable) and not isinstance(arg, str) class DeepNamespace(SimpleNamespace): def namespacesFromIterable(self, arg): vals = [] changed = False for x in arg: not_iterable = True try: x.items value = type(self)(**x) changed = True not_iterable = False except AttributeError: if isIterableNotStr(x): value = self.namespacesFromIterable(x) changed = True not_iterable = False if not_iterable: value = x vals.append(value) if changed: return tuple(vals) return arg def __init__(self, **kwargs): super().__init__(**kwargs) for k, v in kwargs.items(): try: v.items except AttributeError: if isIterableNotStr(v): self.__setattr__(k, self.namespacesFromIterable(v)) else: self.__setattr__(k, type(self)(**v)) Notice that if the dict contains at any level an iterable that is not a string or a dict-like object, this is converted to a tuple. Probably there's a smarter way to maintain the original iterable type. -- https://mail.python.org/mailman/listinfo/python-list