致阅读本文的各位
本文面向 Python 学习新手
帮助各位巩固 Python 的基础
并无“晦涩,学术,看起来 * 炸天的文字”
放心食用~
不知各位在 Python 比较运算符的学习中,是否遇到下面离谱的问题:
——————————————————
Qst1:
我们创建了两个变量 a ,b
并都给它们赋值为 30
>>> a = 30
>>> b = 30
开始以下测试:
>>> a == b
True
使用 == 运算符 比较 a , b,
返回True值
>>> a is b
True
使用 is 运算符 比较 a , b,
也返回True值
此时你对 is 的作用处于云里雾里的状态
就在以为 [ == ] 和 [ is ] 不过是 王老吉 和 加多宝 的关系时
我们将 a 和 b 的数值变大一点
>>> a = 300
>>> b = 300
继续测试:
>>> a == b
True
嗯嗯嗯,== 运算符比较的是大小,
没毛病
>>> a is b
False
嗯???
于是,你露出了这个表情
为什么当变量的数值不同的时, is运算符的返回值也不同呢?
就在你以为 is 不过是 == 的替身之时,加多宝摇身一变,变成了肾宝。
is : 嘿嘿~ 想不到吧?
——————————————————
原因分析
首先,我们来看点干货
当程序从变量中取值,实际上是通过变量名找到相应的内存地址,从其存储单元中读取数据
也就是说,变量不仅仅只有 数值(value) 这个属性,其实它也指向了内存中的一块地址。
[ == ] 和 [ is ]的作用
== : 比较的是两个变量或常量的 数值(value) ,只要它们的数值相同,就返回True值
is : 比较的是两个变量或常量的内存地址,只要它们指向了同一个内存地址,就返回True值
可以理解为:
把变量当成一个女孩子,叫 小 a 吧。
is 只是知道她在哪儿,她的地址而已,并不知道她长什么样,她的具体数值(审核大大明鉴,没开车,真没开,讲原理呢。)
当出现一个小b、小c,小d.......住在同一个地方时,is还傻傻的以为她们是同一个人。
而 == 就不一样了,直接进入小a的地址,知道了她长什么样。
——————————————————
Python特性
Python的原生解释器,为了更加效率和经济的考虑,预先把 -5 ~ 256 范围的整型数值创建了内存地址。
所以当给a,b变量赋值为30时,会将变量分配到30预先创建的内存地址。当变量的值发生改变,且不在预先分配范围内( -5 ~ 256 )的时候,就会给这个变量新创建一个内存空间。
一开始就给a,b赋值300也是如此,不在范围内,新分配一个地址。
——————————————————
Qst2:
理解了上面的问题,于是,你想换一个方法继续给a,b赋值
>>> a = 300; b = 300
然后继续使用 is 来比较它们
>>> a is b
True
就在你认为会返回False的值的时候
它又给了你一个惊喜
于是,你又露出了这个表情:
——————————————————
交互式与IDE
>>> a = 300
>>> b = 300
当你在日后的Python学习中看到 >>> 符号时,其实用的是交互式方式编程。
在这种模式下编程的时,当你输入完一行,敲下回车键的那一刻时,该行语句就会被解释器执行。所以你敲的这两行代码的执行时间是不一样的,解释器先接收到了要给a创建内存空间的信号,后来才收到要给b创建内存空间的信号,时间不一样。
到这里,我想,聪明的你应该理解了为什么执行
>>> a = 300; b = 300
这行代码的时候,会导致它们的 is 运算后会返回True值。
因为它们被放在了一行。
解释器同时收到程序的信号,在给它们分配内存空间时,发现它们的数值是一样的,为了更经济的考虑,给它们分配了同一个内存空间。
换行是Python中语句的结束符,而 ; 号也是语句结束符。
通常情况下,如果想把两个语句放在一行执行,则需要用到 ; 号结束符。
而在IDE中,如VS Code,Pycharm,诸如此类的集成式编辑器。这样的编程模式中,是写完了所有代码,再交给编辑器按顺序执行。即使你把a和b的赋值放在了上下两行,也可能因为它们离得很近,其关联性高,从而同时执行两行代码。
——————————————————
预分配范围求值代码
#手机用户食用提示
#横过来打开全屏观看~
import time #导入该模块是为了每行循环时暂停一小会儿
a = -127; b = -127
flag = 0; n = 0
min = 0; max = 0
while(n < 2):
a, b = a + 1, b + 1 #每轮循环自增计算
print(f"{a : 4d} is {b : 4d}: {a is b}")
if(a is b and flag == 0):
min = a
flag += 1
n += 1
elif(a is not b and flag == 1):
max = a - 1
n += 1
if(n == 2):
print(f"\nPython原生解释器预先为{min} ~ {max}创建了内存空间。")
time.sleep(0.1) #每轮睡眠一会儿是想让程序显示的速度慢一点,方便查看。
#当然,你复现的时候也可以注释掉。
该程序的主要思想,就是想从-127开始,逐渐递增,然后查看什么时候它们的 is 运算能返回True值,便记录下来。
关于为什么把自增计算提前,是为了避开那两个变量的初始值。根据上面的知识,我们知道,因为两个赋值语句离得很近,解释器会把它们放在同一个内存空间中,这样会导致一开始得 is 判断直接返回True值,这不是我们所要捕捉的情况。
致阅读至此的,我的朋友:
真诚地感谢你读到这里
如果能帮到你,不胜荣幸
很开心能和你分享一些,属于我的见解
有缘再见咯~
To阅读本文大佬的免责声明(听我狡辩):
因为本文的目标是
帮助新手理解Python基础的一些知识
所以采用了比较口语化的词汇
衷心欢迎各位提出意见指正