比较判断逻辑是在代码中常常使用的,在Python中经常使用 '==' 和 is 来作比较判断。python
# 按照逻辑,下面的代码很正常 >>> a = 1 >>> b = 1 >>> a == b True >>> a is b True >>> id(a) 1570522768 >>> id(b) 1570522768 # 下面就是颠覆认知的时刻 >>> a = 1000 >>> b = 1000 >>> a == b True >>> a is b False >>> id(a) 81183344 >>> id(b) 81183376
是的,两个相同值的变量,内存地址不同了。固然产生这个现象的前提条件是用python命令行去执行,而不是用pycharm之类的编辑器。其根本缘由也就是python解释器的问题,涉及到python的垃圾回收机制。上面现象的缘由是由于一个叫作小整数对象池的东西。缓存
Python为了优化速度,会把 [-5, 256] 之间的数据提早存放在小整数池中,若是程序使用到小整数池中的数据,是不会开辟新的内存空间去建立,而是指向对象池中的同一份数据,也就是说有N个变量等于1的话,那么这N个变量的内存地址都会指向小整数池中的1位置。小整数池的使用是为了不整数频繁申请和销毁内存空间。小整数池是提早创建好的,不会被垃圾回收。编辑器
当数据超出小整数池后,也就是范围到了大整数对象池中了,系统每次都会申请一块新内存来存储数据,这个'is'不等于'=='的现象也就不存在了。函数
pycharm中,每次运行是全部代码都加载到内存中,属于一个总体,并不存在这个现象。性能
# 先来个正常的 >>> a = 'qwe' >>> b = 'qwe' >>> a == b True >>> a is b True >>> id(a) 81797024 >>> id(b) 81797024 # 感受没什么变化,那就加长一些 >>> a = 'q' * 20 >>> b = 'q' * 20 >>> a is b True >>> a == b True # 在长点就不同了 >>> b = 'q' * 21 >>> a = 'q' * 21 >>> a is b False >>> a == b True >>> id(a) 81811696 >>> id(b) 81811600
产生缘由:Python的intern机制。优化
简单理解有点像缓存的意思,当须要使用相同的字符串时(变量赋值),直接从缓存中拿出来用而不是从新建立,这样能够避免频繁的建立和销毁,提高效率,节约内存。缺点是拼接字符串,对字符串修改之类的影响性能。由于是不可变的,因此对字符串修改不是inplace操做,而是新建对象。这也就是拼接字符串的时候不建议是用 '+' 方法,而是推荐用join 函数,join函数是先计算出全部字符串的长度,而后一一拷贝,而只建立一次对象。每一个'+'方法都是建立一次新对象。当字符串长度超过20时,也不会使用intern机制。spa
并非全部的字符串都会采用intern机制。只包含下划线,字母(包含大小写),数字的字符串才会被intern。空格和一些特殊字符都不在内。也就是说字符串中若是包含空格和其余一些特殊符号(除去下划线),python都不会应用intern机制,而是直接开辟新的内存空间去存储。命令行
# 注意下面这种看似合理的字符串intern >>> 'ab' + 'c' is 'abc' # 这里的字符串,'ab' + 'c' 是在complie time 求值的,被替换成了'abc' True >>> n1 = 'ab' >>> n2 = 'abc' >>> n1 + 'c' is n2 # n1 + 'c' 是在run-time拼接,致使没有被自动intern False >>> n1 + 'c' is 'abc' False >>> n1 + 'c' == 'abc' True >>> n1 + 'c' == n2 True