致阅读本文的各位

本文面向 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

嗯???

于是,你露出了这个表情

python A类需要使用B类中的变量_Python

 为什么当变量的数值不同的时, 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的值的时候
它又给了你一个惊喜

于是,你又露出了这个表情:

python A类需要使用B类中的变量_Python

——————————————————

 交互式与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基础的一些知识

所以采用了比较口语化的词汇

衷心欢迎各位提出意见指正