Python 如何知道两个字符串变量指向同一个对象? [复制]

Posted

技术标签:

【中文标题】Python 如何知道两个字符串变量指向同一个对象? [复制]【英文标题】:How does Python know two string variables point to the same object? [duplicate] 【发布时间】:2018-12-15 08:40:03 【问题描述】:

我是 Python 新手,不得不说 Python 处理变量赋值和函数参数的方式非常令人困惑。这是我不明白的事情。如果我定义了两个具有明确相同内容的字符串,例如“abc”,那么它们实际上是同一个对象,如下所示。

x = 'abc'
y = 'abc'
x is y
True

这让我想到 Python 是如何知道它们是相同的。通过比较代码中的文字?如果在 x = 'abc' 和 y = 'abc' 之间发生了数百万种不同的事情,Python 是否会一直返回并说已经有一个对象 'abc' 所以我不打算创建一个新的 'abc'?

我想知道如果我这样做但使用一个非常长且复杂的字符串会发生什么。这就是发生的事情。

x = 'nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@'
y = 'nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@'
x is y
False
x == y
True

现在你可以明白我为什么感到困惑了。所以 Python 在创建新字符串对象时只检查“简单”字符串而不检查长字符串?那么到底有多复杂/多长才算太复杂/长呢?

【问题讨论】:

这个细节是特定于实现的。 Python 允许实现共享它知道是不可变的任何值的实例,但从不需要它,因此任何依赖于x is yx is not y 的代码在此处为 true 都会被破坏,或者充其量是不可移植的。如果您想了解特定实现的内部实现细节,例如 CPython 3.7、CPython 2.7 或 PyPy 2.1/3.5,或者如果您想大致了解 Python 实现可以在此处使用的含义,这些实际上都是单独的问题。 【参考方案1】:

x is yx==y 存在差异x is y 将检查 x 和 y 是否指向堆中的同一个对象。 而x == y 会检查 x 和 y 的值是否相同。

现在让我们看看为什么会得到这两个不同的结果

如果值的长度很小(最多 3 到 4 位),则 python 检查堆中是否存在具有相同值的另一个对象。如果存在则它不会创建新对象,并且如果不存在,它会创建新对象。 如果值的长度很大(超过 4 位)python 创建新对象,它不会检查具有相同值的对象是否已经存在。

当string,int,float的长度很小时

在 python 中,当 two variables 具有 same string,int or float valueif the length of value is small 时,两个变量都指向同一个对象,即只有一个对象被创建在堆内存中。 让我们通过这个例子自己尝试。

a=10
b=10
a is b
True     #output
a == b
True     #output  

a is b 在这里检查 a 和 b 是否引用(即指向)堆中的同一对象。 由于 10 的长度为 2 很小,python 解释器只会创建一次对象值 10,这就是为什么 a 和 b 将引用同一个对象而 output is True

a == b 将检查 a 的值是否等于 b 的值。 由于 a 的值为 10,b 的值为 10 所以output is True

您也可以尝试使用字符串值,例如

s1='abc'
s2='abc'
s1 is s2
True      #output
s1 == s2
True      #output  

当string,int,float的长度很大时

现在当string,int,float的长度很大时python解释器不会检查堆中是否存在具有相同值的对象,即使存在具有相同值的对象也会直接创建新对象

x = 'nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@'
y = 'nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@'
x is y
False
x == y
True

由于nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@ 太长,python 解释器不会检查堆中是否存在另一个具有相同值的对象,它将创建一个对象,x 将引用该对象。 现在再次将nao;uh gahasjhd;fjkhag;sjdgfuiwgfashksghdfaihghehwq3473fsd_@ 分配给y,但由于字符串的长度很大,python 解释器将创建新对象(即使该对象已经存在也很难) 现在由于xy 引用不同的对象输出将是False 由于xy 具有相同的值输出将是True

你也可以试试这个,例如

a = 10000
b = 10000
a is b
False      #output
a == b
True      #output  

为什么 Python 会这样做

Python 这样做是为了减少解释时间(即代码的执行时间) 如果python不断检查长字符串(例如长度为10)是否已经存在于堆中。它将需要更多时间,因为它将逐个字母与所有对象进行比较。比较10位数字会耗费大量时间。 而如果字符串的长度小于 4,则比较容易比较(因为只需要比较 3 个字母)并且不会花费太多时间。

【讨论】:

感谢您花时间解释它。根据我得到的回复,我现在明白这是字符串实习的问题。但是一个字符串是否被实习不仅仅取决于它的长度是否为 4 或更少,它与长度、字符串类型以及其他一些因素有关。正如其中一个答案所指出的那样,它是特定于实现的。 没问题?。重要的是你已经明白了 字符串太长不是为什么...我仍然不知道...我将在下面发布反例如果您将所有特殊字符替换为字母或数字(在本例中为 X)它们是同一个对象,即使是长字符串... x = 'naoXuhXgahasjhdXfjkhagXsjdgfuiwgfashksghdfaihghehwq3473fsdXX' y = 'naoXuhXgahasjhdXfjkhagXsjdgfuiwgfashksghdfaihghehwq3473fsdXX' print(x is y) # 给出 True

以上是关于Python 如何知道两个字符串变量指向同一个对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如果两个变量指向同一个对象,为啥重新分配一个变量不会影响另一个?

python 对象和内存的关系

Swig:将成员变量(指向值的指针)转换为 python 列表

python变量引用拷贝之间的关系

Python对象

python需要设置哪些环境变量?我只知道一个PYTHONHOME指向安装目录。