为什么ʻis`运算符在脚本中的行为与REPL不同? [英] Why does the `is` operator behave differently in a script vs the REPL?

查看:70
本文介绍了为什么ʻis`运算符在脚本中的行为与REPL不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python中,两个代码有不同的结果:

In python, two codes have different results:

a = 300
b = 300
print (a==b)
print (a is b)      ## print True
print ("id(a) = %d, id(b) = %d"%(id(a), id(b))) ## They have same address

但是在shell模式下(交互模式):

But in shell mode(interactive mode):

>>> a = 300
>>> b = 300
>>> a is b
False
>>> id(a)
4501364368
>>> id(b)
4501362224

是运算符的结果不同。

推荐答案

.py 脚本中运行代码时,整个文件编译到代码对象执行它。在这种情况下,CPython可以进行某些优化-例如为整数300重新使用同一实例。

When you run code in a .py script, the entire file is compiled into a code object before executing it. In this case, CPython is able to make certain optimizations - like reusing the same instance for the integer 300.

您还可以通过执行以下代码在REPL中重现该实例:

You could also reproduce that in the REPL, by executing code in a context more closely resembling the execution of a script:

>>> source = """\ 
... a = 300 
... b = 300 
... print (a==b) 
... print (a is b)## print True 
... print ("id(a) = %d, id(b) = %d"%(id(a), id(b))) ## They have same address 
... """
>>> code_obj = compile(source, filename="myscript.py", mode="exec")
>>> exec(code_obj) 
True
True
id(a) = 140736953597776, id(b) = 140736953597776

其中一些优化非常激进。您可以修改脚本行 b = 300 ,将其更改为 b = 150 + 150 ,CPython仍然会折叠将 b 转换为相同的常量。如果您对此类实现细节感兴趣,请查看 peephole.c 和Ctrl + F用于 PyCode_Optimize 以及有关 consts table的任何信息

Some of these optimizations are pretty aggressive. You could modify the script line b = 300 changing it to b = 150 + 150, and CPython would still "fold" b into the same constant. If you're interested in such implementation details, look in peephole.c and Ctrl+F for PyCode_Optimize and any info about the "consts table".

相反,当您直接在REPL中逐行运行代码时,它将在不同的上下文中执行。

In contrast, when you run code line-by-line directly in the REPL it executes in a different context. Each line is compiled in "single" mode and this optimization is not available.

>>> scope = {} 
>>> lines = source.splitlines()
>>> for line in lines: 
...     code_obj = compile(line, filename="<I'm in the REPL, yo!>", mode="single")
...     exec(code_obj, scope) 
...
True
False
id(a) = 140737087176016, id(b) = 140737087176080
>>> scope['a'], scope['b']
(300, 300)
>>> id(scope['a']), id(scope['b'])
(140737087176016, 140737087176080)

这篇关于为什么ʻis`运算符在脚本中的行为与REPL不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆