本文整理了很多字符串所在的坑,部分集成自wtfpython英文版,并增加了很多后续说明。#example1:>>>a="wtf">>>b="wtf">>>aisbTrue#example2:>>>a="wtf!">>>b=“卧槽!”>>>a是bFalse#example3:>>>a,b="wtf!","wtf!">>>aisbTrue#3.7版本返回False。#example4:>>>'a'*20is'aaaaaaaaaaaaaaaaaaaa'True>>>'a'*21is'aaaaaaaaaaaaaaaaaaaaaaa'False#3.7版本将这些问题的结果作为True字符串返回,就好像告诉你1!=1是作弊。原因是CPython在编译的时候会自动优化。在某些情况下,它会尝试使用现有的不可变对象而不是创建新对象,而字符串是不可变对象。这种使用现有不可变对象的行为称为“持久化”。驻留的设计初衷是为了节省内存,但有时确实会坑程序员。如何判断自己的字符串是否会常驻?请看这段代码:https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19简单地说:1.所有长度为0和1的字符串都将常驻2.Stringsthatimplementedat编译时会常驻(比如'wtf'会常驻,但是''.join(['w','t','f'])不会)3.Strings只能是ASCII下的字母、数字和下划线将常驻。所以'卧槽!不会驻留,因为它包含!。在我们的example1中,a和b是同一个字符串对象,因为驻留。在示例2中,由于没有出现字符串驻留,因此a="wtf!"和b="wtf!"实际上使用的不是同一个字符串对象,可以通过id获取对象的唯一标识,你会发现它们的区别:a和b都是wtf!:>>>a="wtf!">>>b=“卧槽!”>>>aisbFalse>>>a==bTrue>>>id(a)2272774097864>>>id(b)2272774097024我们看一下没有常驻时的情况,当a和b都为wtf时:#a和b是wtf>>>a="wtf">>>b="wtf">>>a是bTrue>>>a==bTrue>>>id(a)2272774096744>>>id(b)2272774096744知道了吗?如果要从结果中判断对象是否常驻,关键是看对象的唯一标识是否发生了变化。但是,如示例3所示,当您将a和b都设置为wtf!在同一行,Python解释器将创建一个新对象,然后同时引用第二个变量。身份证是一样的。(example3只适用于python3.7及以下,后来改了)。example4中出现了constantfolding,这其实是一种优化技巧。编译时,表达式'a'20会被'aaaaaaaaaaaaaaaaaaaa'代替(不算,20),但是只有长度小于20的字符串才会被常量代替,这就是'a'21不等于的原因到'aaaaaaaaaaaaaaaaaaaaaa'(不算数,21)。嗯,感谢阅读,今天的.....等等,你以为这就结束了吗?另外:>>>a=10>>>b=10>>>a是bTrue>>>a=256>>>b=256>>>a是bTrue>>>a=257>>>b=257>>>a是bFalse为什么?请注意,在Python中,对于一个整型对象,如果它的值在闭区间[-5,256]内,那么具有相同值的对象就是同一个对象,否则就是不同的对象。我知道你想问,别问,问题是源码本身是这样写的(其实主要是从性能上看,经常使用-5到256之间的值,所以简单地设置为同一个对象重复使用,避免分配空间——分配类别——分配初始值等一系列操作)。这是我们文章的结尾。如果你今天想要我们的Python教程,请继续关注我们。如果对您有帮助,请在下方点赞或观看。如果您有任何问题,可以在下方留言区留言。我们会耐心解答!Python实战宝典(pythondict.com)不只是一个合集欢迎关注公众号:Python实战宝典
