Python 中是否存在空类?

11

在Python中是否存在特殊的类用于创建空对象?我尝试使用object(),但它不允许我添加字段。 我希望能像这样使用它:

obj = EmptyObject()
obj.foo = 'far'
obj.bar = 'boo'

我每次(在几个独立的脚本中)都需要像这样定义新类吗?

class EmptyObject:
    pass

我使用Python 2.7。


2
这是两行相当自明的代码,我认为重复它没有问题。即使你必须添加一个新的import来获取现有的EmptyObject,净节省也将很小。 - user4815162342
你甚至可以把它放在一行上,不是吗? - 2rs2ts
1
你考虑过namedtuple吗?我有一种感觉,你正在重新发明轮子。 - kojiro
1
@2rs2ts 就像 Bunch 一样。个人认为这是产生问题的好方法。 - kojiro
你有考虑过使用attrdict吗?市面上有很多实现方式。 - cmd
显示剩余2条评论
4个回答

10

types.SimpleNamespace 是在 Python 3.3 中引入的,旨在实现这一具体目的。文档还展示了一个简单的方法来在 Python 中自己实现它,以便将其添加到您的 Python 3.3 之前的设置中,并像已经存在一样使用它(请注意,实际的实现是用 C 完成的)。

class SimpleNamespace (object):
    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__

当然,如果您不需要它的几个功能,一个简单的 class Empty: pass 就可以做到同样的事情。


很不幸,正如我所说的,我使用的是Python2.7。 - sbeliakov
4
正如我所说,你可以轻松地将这个实现添加到你的 Python 2 项目中,并像它一样使用它。 - poke
2
OP担心每个脚本都要重复这两行琐碎的代码。相比之下,每个脚本都重复这9行代码似乎更像是一种治疗方法,而不是解决问题的办法。 - user4815162342
@user4815162342 类型定义可以 - 而且应该 - 轻松地移动到单独的模块中,特别是当您从不同位置多次访问该类型时。 - poke
单独的模块是一个新的依赖项,这使得将脚本分发到不同的机器上变得更加困难而不是更容易。虽然可以做到,但这是一种权衡。在问题的背景下,问题要求如何避免创建空容器类的两行代码,为这两行代码创建一个单独的模块显然过于复杂。 - user4815162342
显示剩余2条评论

8

如果你正在寻找一个占位符对象,可以向其中添加任意静态成员,那么我推荐使用空的lambda函数。

obj = lambda: None    # Dummy function
obj.foo = 'far'
obj.bar = 'boo'

print obj.foo, obj.bar
# far boo

注意:obj 不是类的对象,object 并不意味着 class instance,因为在 Python 中,类和函数在运行时与类实例一样作为对象处理。


1
为什么要使用参数?你同样可以使用 lambda: 0。尽管如此,我仍然不会使用它,因为这使得很难弄清楚你首先为什么要创建这个 lambda - Martijn Pieters
9
嗯...虽然这很有趣,但我绝对不想在生产代码中看到这个。 - Lukas Graf
我对原创性表示赞赏,但我同意Lukas Graf的观点,这个解决方案不适用于生产。 - sbeliakov

7

在 Python 2.7 中没有 types.SimpleNamespace,您可以使用 collections.namedtuple() 来代替不可变对象:

>>> from collections import namedtuple
>>> FooBar = namedtuple('FooBar', 'foo bar')
>>> FooBar('bar', 'foo')
FooBar(foo='bar', bar='foo')

或者 argparse.Namespace
>>> from argparse import Namespace
>>> o = Namespace(foo='bar')
>>> o.bar = 'foo'
>>> o
Namespace(bar='foo', foo='bar')

另请参阅:如何创建一个对象并添加属性?


1
酷!又一个使用argparse的理由! - nealmcb

2
您可以使用type函数动态创建具有所需字段的新类型,如下所示:
x = type('empty', (object,), {'foo': 'bar'})
x.bar = 3
print(x.foo)

然而,这并不完全是您想要的,因为它将具有自定义类型,而不是空类型。


此外,每次调用都会创建一个新类型,这相当昂贵。 - user4815162342

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接