我正在学习python(3.6),我发现了以下内容:
a = "hi"
b = "hi"
a == b #True
a is b #True
a = list(a)
b = list(b)
a = "".join(a)
b = "".join(b)
a == b #True
a is b #False
为什么转换为list并加入字符串后结果会有所不同?我知道Python VM维护一个字符串池,因此a和b的引用相同。但是为什么在将列表加入到相同的字符串后这不起作用?
谢谢!
答案 0 :(得分:1)
除了单身人士(如None
,True
或False
)与is
之外,你不应该真正比较任何事情。因为is
并不真正比较内容,所以它只检查它是否是同一个对象。因此,如果您将具有相同内容的不同对象进行比较,则is
将失败。
您的第一个a is b
工作的事实是因为文字被实习(*)。因此a
和b
是同一个对象,因为两者都是具有相同内容的文字。但这是一个实现,它可能会在未来(或更旧的)Python版本中产生不同的结果,因此不要在它现在可用的基础上开始将字符串文字与is
进行比较。
(*)它确实应该返回False
,因为你编写案例的方式不应该是同一个对象。它们碰巧是同一个,因为CPython优化了一些情况。
答案 1 :(得分:0)
关键在于:
config.xml
string.join()
方法返回一个 new 字符串,它是通过连接列表元素构建的。
每次调用mymodule.php
都会设置一个新字符串:在第一次调用中创建一个字符串,并将其引用分配给a = "".join(a)
b = "".join(b)
,然后在第二次调用中, new string已构建,其引用已分配给string.join()
。因此,两个名称a
和b
引用了两个新的不同字符串,它们本身就是两个独立的对象。
is
运算符按设计运行,将a
作为b
返回,false
不是对同一对象的引用。
如果您正在尝试查看两个字符串的内容是否相等,那么运算符==
可能是更好的选择。
答案 2 :(得分:0)
有很多方法可以解决这个问题,但是您可以在这里考虑内存。 RAM中构成数据的物理位。在python中,关键字“ is”检查两个对象的地址是否完全匹配。运算符“ ==”通过运行magic方法中定义的比较来检查对象的 value 是否相同-负责将运算符转换为函数的python代码-必须对此进行定义每堂课有趣的部分来自它们本来是相同的事实,这个问题应该可以帮助您。 when does Python allocate new memory for identical strings?。
从本质上讲,python可以优化“ hi”字符串,因为在运行代码之前已对它们进行了键入,因此它会创建一个包含所有键入字符串的表,以节省内存。当从列表构建字符串对象时,python不知道内容将是什么。默认情况下,在您的特定版本的解释器中,这意味着将创建一个新的字符串对象-这样可以节省检查重复项的时间,但需要更多的内存。如果要强制解释器检查重复项,请使用“ sys.intern”函数:https://docs.python.org/3/library/sys.html
sys.intern(字符串):
在“ interned”字符串表中输入string并返回被插入的字符串–它是字符串本身或副本。插入字符串对于提高字典查找的性能很有用-如果字典中的键被插入,并且查找键被插入,则键比较(散列后)可以通过指针比较而不是字符串比较来完成。通常,Python程序中使用的名称会被自动插入,并且用于保存模块,类或实例属性的字典具有插入键。 实习弦不是不朽的。您必须保留对intern()返回值的引用,以从中受益。