Skip to content

Latest commit

 

History

History
331 lines (241 loc) · 9.07 KB

129-203108-值比较与地址比较_is.sy.md

File metadata and controls

331 lines (241 loc) · 9.07 KB
show version enable_checker
step
1.0
true

比较运算符

回忆

  • 这次研究了以下类的比较运算符
    • 映射类 map
      • dict 字典
    • 集合类
      • set
      • frozenset
  • dict
    • 可以比较相等和不等
      • 完全一致就等
      • 不一致就不等
  • 集合类
    • set 和 frozenset 规律相同
    • 一样就相等
    • 不一样就不等
    • 有子集关系的话
    • 可以比较出大小
    • 否则比大小结果都是 False
  • 比较运算符还有
    • 对称性
    • 传递性
    • 否定之否定原理
  • 除了这些还有什么比较运算符么?🤔

是否相等 is

  • 先试试吧

图片描述

  • 验证一下密码
  • 字符序列的比较
  • is 是可以用的
  • 数字的比较呢?

数字 is

图片描述

  • is 可以用
  • 但是会报一个警报
  • 语法警报
  • SyntaxWarning
  • 这是从 python3.8 开始的
  • 这类比较建议还是用 ==!=
  • 计算结果可以用 is 么?

计算

图片描述

  • 加减法是可以出结果
  • 但是还是有警报
  • 乘除法出了问题
  • 这是为什么呢?

求值

图片描述

  • 这个除法的结果是一个 float 类型的变量
  • is 对不同类型的变量的比较的结果是 False
  • 想要得到正确答案还需要进行类型转化
  • 或者使用整除运算符
  • 而 == 可以对如下类型比较
    • int 整型
    • float 浮点型
    • complex 复数
    • fractions 分数
    • decimal 精确十进制
  • 判断的时候内存里面什么样呢?

动手

  • a、b
    • 类型相同
    • 所指向的内存地址相同
    • 两个变量的值相同

图片描述

  • 所以==和 is 都直接好用

图片描述

  • 字符串呢?

字符串

  • 字符串也是这样的

图片描述

  • 变量名只是一个装东西的盒子
  • 两个变量进行运算符==的比较
    • 其实就是在比较两个盒子里放的东西是否相等
    • 如果盒子里放的都是"oeasy"
    • 那么说"oeasy" 就是"oeasy"
    • 这句话是正确的
  • is 看看内存里的情况
    • 如果这两个字符串指向同一个位置
    • 就说 (s1 is s2) 为 True
  • 这还是存有具体字符串的变量
  • 如果字符串等于 None 会如何呢?
  • 首先什么是 None?

None

图片描述

  • None 是由函数返回的
  • 简单来说就是啥都不是

图片描述

  • 听起来有点像 float("nan")
    • not a number
  • float("nan") == float("nan") 是 False
  • 那 None 是否等于 None 呢?

比较

图片描述

  • None == None 可以得到 True
  • None is None 也可以得到 True
  • 目前看起来 == 和 is 完全一致啊
  • 他们有什么区别吗?
  • 查询帮助
  • 到底什么是is

帮助

图片描述

  • 如果两个栈 Frame 变量是指向同一个堆 Heap 空间
  • 或者说他们 Frame 上存储的值相同
  • 或者说他们的 id 相同
  • 那么 is 就好使

图片描述

  • None 在 Heap 堆上的值是固定的

图片描述

  • 这都是直接存在 Frame 帧栈上的
  • 我能看到到底什么是 Heap 堆么
  • 里面存了些什么东西?

容器

图片描述

  • 这样就可以看出==和 is 的区别了
  • e、f 是两个指向不同 heap 区的集合
  • heap 堆就对应下图中右边 Objects 的黄色部分

图片描述

  • 他们所指向的堆空间的地址不同
    • 所以 is 的结果为 False
  • 而他们的具体集合值相同
    • 所以他们的 == 结果为 True
  • 简单来说
    • == 比较的是具体的值
    • is 比较的是内存中的地址
  • 那怎么得到地址的呢?

帮助

  • 再仔细看看帮助文件

图片描述

  • 帮助手册是这样说的

图片描述

  • 那我来试试用 f 给 e 赋值
  • 结果会如何?

赋值

图片描述

图片描述

跳转到 pythontutor逐步验证

继续深入

图片描述

  • 这次比较的容器是列表
  • 和集合的规律类似
  • 只有 id 相等 is 的结果才为 True
  • 换句话说
    • 得是指向堆空间同一地址 is 才是 True
    • 或者说得是同一个对象 is 才是 True
  • 如果列表里面嵌套列表会如何呢?
    • 继续深入

嵌套

图片描述

图片描述

  • 原理没有变
    • is 比较的是 id
    • == 比较的是值
  • 如果此时我修改 a
  • 会影响到 c 么?
  • 会影响到 c 和 d 是否 == 呢?

修改

图片描述

  • a = [2]
  • 并不会影响到 c 和 d
  • 因为 a 指向了新的列表
  • 而 c[1] 还指向原来的位置
  • 并不受影响
  • 想让他受影响怎么办?

再修改

图片描述

  • a[0] = [2]
  • 这确实可以修改原来 a 列表中的元素
  • 从而修改 c 列表
  • 但是在最后比较的时候
  • c、d 第 0 个元素不分胜负
  • 在第 1 个元素的位置
    • 他们都是列表
    • c 是[[2]]
    • d 是[0]
    • 那么比较这两个列表第 0 个元素的位置
  • 在子列表中第 0 个元素的位置
    • c[1][0]
      • 值是 [2]
      • 类型是个 list
    • d[1][0]
      • 值是 2
      • 类型是个 int
    • 这俩类型无法比较
    • 应该怎么改呢?

跳转到 pythontutor

三修改

图片描述

  • 还得修改 a 的元素 a[0]
  • 通过 a[0]的值从而修改 c[1]的值
  • 这次可以进行比较了
  • 第一轮不分胜负
  • 第二轮面对站的都是列表
  • 进入子列表中都是整型
  • 2 > 0
  • 所以 c > d 是 True
  • 可是定义两个 int 型变量他们怎么会相等呢?

回到最初

图片描述

  • == 与 is 的不同
    • = 比较的是值
    • is 比较的是id
  • 我们换一种说法

例子

  • == 与 is 的不同
    • = 比较的是盒子里面装的地址指向对象的值
    • is 比较的是盒子所在的地址

图片描述

  • 怎么比较盒子所在的地址呢?

id

  • 通过id我们可以得到地址

图片描述

  • 通过is我们可以比较地址
    • is 比较的是 - 两者是否用的同一个盒子
    • 或者说在内存中占的是同一块空间
  • is 和 == 两者什么关系呢?

is 和 ==

图片描述

  • is 的要求比 == 更严格
  • 满足 is 一定满足 ==
  • 满足 == 不一定满足 is

总结

  • 这次研究了 is
  • is 判断是否相等
  • 具体用 == 还是 is 和变量类型相关
  • int、float、str 之类的相等判断最好用 == 和 !=
  • 容器类对象的比较可以灵活运用 is 或者 ==
  • is 为 True 代表两个东西 id 相等
    • 用的是同一个盒子
    • 在内存中占的是同一块空间
  • 我发现了这么个问题

图片描述

  • 同样的代码
    • id时等时不等
    • 这怎么理解?🤔
  • 下次再说 👋