Python中的空不可变对象是单例吗?

9 投票
1 回答
812 浏览
提问于 2025-04-18 17:03

Python中的空不可变对象是单例吗?

如果你查看CPython对内置类型的实现,你会发现有评论提到所有空的不可变对象都是单例。这其实是很有道理的,因为这样Python就可以避免在那些永远不会改变的重复对象上浪费内存。

这里是2.6版本中提到冻结集合的具体源代码。 里面有这样的评论:

/* The empty frozenset is a singleton */

我在CPython 2.5中也找到了同样的评论。我觉得除了文档,查看源代码也是有意义的,因为CPython是Python的参考实现。

我在使用Python 2.6.5时,在我的解释器中得到了以下结果:

>>> g = frozenset()
>>> f = frozenset('a') - frozenset('a')
>>> f
frozenset([])
>>> f is g
False
>>> id(f)
279262312
>>> id(g)
114734544

这是不是意味着这个评论是错的?这是2.6.5中的一个bug吗?在后来的Python版本中有保证吗?如果有,我在文档中找不到相关的说明。

我之所以问这个,是因为我需要一个和(None, '')成员检查相同的东西,但原因另有说法。

这是不是也是为什么通常建议用is来检查None,而用==或者Python对空类型的语义假值来处理其他类型的控制流?

总结一下:

Python的空不可变对象是否有保证是单例?

1 个回答

12

标准类型的描述并没有保证相同的对象是完全一样的,除了TrueFalseNoneNotImplementedEllipsis这几个特殊的值。它并没有承诺像() 是 ()1 是 1、或者'hello' 是 'hello'这样的情况都是成立的。(实际上,文档在3.1的最后一段特别否认1 是 1的要求。)

所以,Python中的空不可变容器并不一定是单例*。唯一可以保证是单例的值就是TrueFalseNoneNotImplementedEllipsis



* 注意:在这个上下文中,“单例”这个词的意思和一般理解的不太一样。在这里,单例指的是只能由一个对象持有的值;这意味着每个包含该值的对象都是完全相同的。

撰写回答