如何解决为什么“is”运算符在算术相等的表达式中表现出乎意料
a = 1000
b = 1000
print (a == b)
print (a is b)
print (f"id(a) = {id(a)} \nid(b) = {id(b)}")
正如我所料
True
True
id(a) = 2806705928816
id(b) = 2806705928816
但是当我尝试做这样的事情时:
a = 1000
b = 1000 + a - a
print (a == b)
print (a is b)
print (f"id(a) = {id(a)} \nid(b) = {id(b)}")
我在表达式 False
中得到了 a is b
True
False
id(a) = 3030783801968
id(b) = 3030783802064
为什么在将表达式的结果分配给整数和带有其他变量的表达式时,变量的行为会有所不同?虽然在数学上这给出了相同的整数。
解决方法
当您执行以下操作时:
(case-1)
a = 1000
b = a
或(案例2)
a = 1000
b = 1000
Python 足够聪明,可以事先知道即使在执行之后您也不需要新内存。
因此,在第一种情况下,python 在执行之前使 b
成为 a
的别名。
第二种情况有点不同。
Python 是真正的面向对象语言,文字 1000
被视为对象。 (直觉上你可以认为 1000 是一个 const 对象的名称)。
所以在第二种情况下,a
和 b
在技术上都是 alias
的 1000
现在在您的示例中:
a = 1000
b = 1000 + a - a
print (a == b)
print (a is b)
在赋值 b
时,python 事先不知道 a
的值是什么。当我说预先时,我的意思是在任何形式的计算开始之前。所以python为b
保留了一个新的内存位置,然后将操作的输出保存在这个新的内存位置。
还有一点值得注意:
4-1 is 3
True
在这种情况下,python 不会用 4-1
保存这一行,而是在编译前将其处理为 3
,以进行运行时优化。
您已经有了一些准确的答案。在这里,我给出了一个“回归基础”的答案。
什么是==
?
Python ==
表示左边的值与右边的值相同。
sum([5,7]) == (48 * 3)**0.5
是 True
。它需要多个求值步骤才能使每个表达式达到 12
的值。即便如此,整数 12
正在与 float 12.0
进行比较,因此需要将整数最终转换为浮点数。
关键要点:每个表达式都被评估,然后比较结果值。如果它们相等,则表达式为真。
什么是is
?
Python is
,另一方面,表示左边的名字和右边的名字指向同一个对象。
a = 3.14159
b = a
a is b
是 True
。 a
已分配给值 3.14159
。但更重要的是,有一块内存保存了一个对象,在这种情况下是浮点数 3.14159。 a
指向该对象/内存块。 b
指向 a
,这意味着它指向同一块内存。
您可以非常轻松地进行测试:创建两个简单指向一个数字的“名称”,然后使用 is
比较它们,它们将不匹配:
>>> a = 1239481203948
>>> b = 1239481203948
>>> a is b
False
这是错误的,因为我们现在在内存/对象中有两个不同的位置分别指向它们:
>>> id(a)
140402381635344
>>> id(b)
140402391174416
(在您的机器上,您将获得一组不同的 id
s。)
因此,实际上,您已经“浪费”了空间,因为您有两个对象占用了相同信息的空间。
等等,还有更多
如果你自己解决这个问题,你会发现我写的内容有吨的异常,并让你自己感到困惑。这里只是一些:
>>> a = 157
>>> b = 157
>>> a is b
True
什么??为什么这是真的?为了优化 Python,“最常见的数字”已经过优化。我可能是错的,但我记得内存中为最常见的数字指定了空间。这些是前几百个整数,以及其他一些。
但也有其他优化:
>>> a = None
>>> b = None
>>> a is b
True
>>> a = True
>>> b = True
>>> a is b
True
这些仍然遵循我之前所说的相同规则:is
评估为 True
的原因是因为 a
和 b
都指向相同的内存/对象中的位置。
由于 Python 中的优化,在这些奇怪的情况下会发生这种情况。 但一般来说,确保 is
的计算结果为 True
的唯一方法是将名称分配给已有名称的对象,就像我们写的那样: >
>>> a = 3.14159
>>> b = a
>>> a is b
True
代替写作
>>> a = 3.14159
>>> b = 3.14159
>>> a is b
False
,
区别在于对位置的引用。 '==' 检查数据类型和值是否相等,但是,'is;引用变量在内存中的位置。
is 将在下面返回 false
id(a) = 3030783801968 <----
id(b) = 3030783802064 <----
is 将在下面返回 true
id(a) = 2806705928816 <----
id(b) = 2806705928816 <----
,
Python 通过将表达式的表达式一一求值来执行语句,然后对这些值执行一些操作。
来源: https://courses.cs.washington.edu/courses/cse140/13wi/eval_rules.pdf
基本上 b = 1000 + a - a 不是一次性完成的,而是在多次评估中,python 将每次评估中 b 的结果存储在与 a 不同的内存位置。此时 a 和 b 是不同的对象。
使用 == 进行相等性检查。
使用“is”来检查对象是否相同(变量引用相同的内存位置)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。