SimpleNamespace和空类定义有什么区别?

Bar*_*uch 33 python python-3.x

以下似乎无论如何都有效.使用的优点(除了好的repr)有什么用types.SimpleNamespace?或者它是一回事吗?

>>> 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'
Run Code Online (Sandbox Code Playgroud)

小智 53

这在类型模块描述中得到了很好的解释.它向您显示types.SimpleNamespace大致相当于此:

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__
Run Code Online (Sandbox Code Playgroud)

与空类相比,这具有以下优点:

  1. 它允许您在构造对象时初始化属性: sn = SimpleNamespace(a=1, b=2)
  2. 它提供了可读性repr():eval(repr(sn)) == sn
  3. 它会覆盖默认比较.它不是比较id(),而是比较属性值.

  • 换句话说1-它允许在构造对象时初始化属性:`sn = SimpleNamespace(a = 1,b = 2)`2-它提供了一个可读的`repr()`:`eval(repr(sn)) == sn` 3-它会覆盖默认比较(通过``继承自`object`的`),以比较属性值. (15认同)
  • 给我带来的最大好处4:它允许我在字典上使用dot.notation。 (5认同)
  • jfs的评论应该是接受答案的一部分. (3认同)
  • 知道为什么 `repr(SimpleNamespace(a=1))` 显示 `"namespace(a=1)"` 吗?我希望它是 SimpleNamespace 而不是简单的命名空间。 (2认同)
  • @Demi-Lune 这是[硬编码](https://github.com/python/cpython/blob/master/Objects/namespaceobject.c#L67)。但是,“SimpleNamespace”的子类实例拥有自己的类名。 (2认同)
  • @martineau我更喜欢直接使用类。我正在使用 PyCharm,它实际上可以显示并填充在 __init__ 中设置为 self 的变量,或者在创建类实例后用点符号设置。(否则它会转到 __slots__ 而不是 __dict__)。感谢您指出 AttrDict。我会看看。 (2认同)

Mil*_*vić 16

Aclass types.SimpleNamespace提供了一种实例化对象的机制,该对象可以保存属性而不能保存其他内容。实际上,它是一个空的类,有一个爱好者__init__()和一个有用的__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')
Run Code Online (Sandbox Code Playgroud)

或者

from types import SimpleNamespace

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

sn.z = 'foo'
del(sn.x)
print(sn)
Run Code Online (Sandbox Code Playgroud)

输出:

namespace(x=1, y=2)
namespace(y=2, z='foo')
Run Code Online (Sandbox Code Playgroud)

这个答案也可能有帮助。