103

The following seems to work either way. What is the advantage (other than the nice repr) of using types.SimpleNamespace? Or is it the same thing?

>>> import types
>>> class Cls():
...     pass
... 
>>> foo = types.SimpleNamespace() # or foo = Cls()
>>> foo.bar = 42
>>> foo.bar
42
>>> del foo.bar
>>> foo.bar
AttributeError: 'types.SimpleNamespace' object has no attribute 'bar'
Baruch
  • 20,590
  • 28
  • 126
  • 201

2 Answers2

146

This is explained pretty well in the types module description. It shows you that types.SimpleNamespace is roughly equivalent to this:

class SimpleNamespace:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        keys = sorted(self.__dict__)
        items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
        return "{}({})".format(type(self).__name__, ", ".join(items))

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

This provides the following advantages over an empty class:

  1. It allows you to initialize attributes while constructing the object: sn = SimpleNamespace(a=1, b=2)
  2. It provides a readable repr(): eval(repr(sn)) == sn
  3. It overrides the default comparison. Instead of comparing by id(), it compares attribute values instead.
martineau
  • 119,623
  • 25
  • 170
  • 301
Matthias Schreiber
  • 2,347
  • 1
  • 13
  • 20
  • 46
    In other words 1- it allows to initialize attributes while constructing the object too: `sn = SimpleNamespace(a=1, b=2)` 2- It provides a readable `repr()`: `eval(repr(sn)) == sn` 3- it overrides the default comparison (by `id()` inherited from `object`), to compare attribute values. – jfs May 11 '16 at 14:31
  • 7
    jfs's comment should be part of the accepted answer. – yig Sep 01 '17 at 14:37
  • 3
    Any idea why `repr(SimpleNamespace(a=1))` displays `"namespace(a=1)"`? I'd expect it to be SimpleNamespace instead of simply namespace. – Demi-Lune May 24 '19 at 11:46
  • 2
    @Demi-Lune It's [hard-coded](https://github.com/python/cpython/blob/master/Objects/namespaceobject.c#L67). However, `SimpleNamespace`'s subclasses instances get their own class name. – Nuno André Sep 10 '19 at 07:56
  • 10
    To add biggest benefit to me 4: it allows me to use dot.notation on dictionaries. – Anssi Nov 08 '19 at 09:43
  • @Anssi: I assume you mean when one is used instead of a dictionary, correct? – martineau Nov 14 '19 at 00:12
  • @martineau like this:`ns = types.SimpleNamespace(**{'a':1})` but now i have come to conclusion that is might be just easier to use classes instead of hacks like this. I am still learning good coding convention for Python. It is more difficult i first thought. – Anssi Dec 11 '19 at 12:41
  • @Anssi: It's possible to create a dictionary subclass that supports dot nation as well as all the usual dictionary methods. Do a web search on the term "AttrDict". – martineau Dec 11 '19 at 14:00
  • 2
    @martineau i prefer to use classes directly. I am using PyCharm and it can actually show and fill the variables set to self in __init__ or set with dot notation after the instance of class have been made. (otherwise it goes to __slots__ not __dict__). Thanks for pointing out AttrDict. I will check it out. – Anssi Dec 17 '19 at 12:10
14

A class types.SimpleNamespace provides a mechanism to instantiate an object that can hold attributes and nothing else. It is, in effect, an empty class with a fancier __init__() and a helpful __repr__():

>>> from types import SimpleNamespace
>>> sn = SimpleNamespace(x = 1, y = 2)
>>> sn
namespace(x=1, y=2)
>>> sn.z = 'foo'
>>> del(sn.x)
>>> sn
namespace(y=2, z='foo')

or

from types import SimpleNamespace

sn = SimpleNamespace(x = 1, y = 2)
print(sn)

sn.z = 'foo'
del(sn.x)
print(sn)

output:

namespace(x=1, y=2)
namespace(y=2, z='foo')

This answer may also be helpful.

Milovan Tomašević
  • 6,823
  • 1
  • 50
  • 42