python - 在什么情况下相等的字符串共享相同的引用?

标签 python string reference immutability

我已经在网络和堆栈溢出问题上进行了搜索,但无法找到该问题的答案。我所做的观察是,在 Python 2.7.3 中,如果您为两个变量分配相同的单个字符串,例如

>>> a = 'a'
>>> b = 'a'
>>> c = ' '
>>> d = ' '

然后变量将共享相同的引用:

>>> a is b
True
>>> c is d
True

对于一些较长的字符串也是如此:

>>> a = 'abc'
>>> b = 'abc'
>>> a is b
True
>>> '  ' is '  '
True
>>> ' ' * 1 is ' ' * 1
True

但是,在很多情况下(意外地)未共享引用:

>>> a = 'a c'
>>> b = 'a c'
>>> a is b
False
>>> c = '  '
>>> d = '  '
>>> c is d
False
>>> ' ' * 2 is ' ' * 2
False

谁能解释一下这是什么原因?

我怀疑解释器和/或某些缓存机制可能会进行简化/替换,这些缓存机制利用 python 字符串在某些特殊情况下不可变的事实进行优化,但我知道什么?我尝试使用 str 构造函数和 copy.deepcopy 函数深度复制字符串,但字符串仍然不一致地共享引用。

我遇到问题的原因是因为我在为新型 python 类的克隆方法编写的某些单元测试中检查对字符串的引用是否不相等。

最佳答案

何时缓存和重用字符串的详细信息取决于实现,可以从 Python 版本更改为 Python 版本并且不能依赖。如果要检查字符串是否相等,请使用 ==,而不是 is

在 CPython(最常用的 Python 实现)中,出现在源代码中的字符串字面量总是被驻留的,所以如果相同的字符串字面量在源代码中出现两次,它们最终将指向同一个字符串对象.在 Python 2.x 中,您还可以调用内置函数 intern()强制保留特定字符串,但实际上您不应该这样做。

编辑 关于您检查属性是否在实例之间不正确共享的实际目的:这种检查仅对可变对象有用。对于不可变类型的属性,共享对象和非共享对象之间没有语义差异。您可以使用

从测试中排除不可变类型
Immutable = basestring, tuple, numbers.Number, frozenset
# ...
if not isinstance(x, Immutable):    # Exclude types known to be immutable

请注意,这也会排除包含可变对象的元组。如果您想测试这些,您需要递归地下降到元组。

关于python - 在什么情况下相等的字符串共享相同的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11611750/

相关文章:

python - 在 Fedora 中使用 Openlayers proxy.cgi?

java - 在返回变量之前检查数组中的所有位置

c++ - c++中关于const成员函数的问题

javascript - 通过引用javascript传递原始变量

python - SQLAlchemy:如何在多个插入语句中将字符串值转换为日期?

python - 分块加载 csv 文件

python - save(commit=False) 抛出验证错误

c++ - 迭代/递归

c - 数组不在 C 中存储/显示整个字符串

java - 读取字符串作为对变量的引用