临摹微笑
当您在.py脚本中运行代码时,整个文件在执行之前会被编译成一个代码对象。在这种情况下,CPython 能够进行某些优化——比如对整数 300 重用相同的实例。您还可以通过在更类似于脚本执行的上下文中执行代码来在 REPL 中重现它:>>> 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) TrueTrueid(a) = 140736953597776, id(b) = 140736953597776其中一些优化非常激进。您可以修改脚本行,b = 300将其更改为b = 150 + 150,CPython 仍会“折叠”b为相同的常量。如果您对此类实现细节感兴趣,请查看peephole.c和 Ctrl+FPyCode_Optimize以及有关“consts 表”的任何信息。相反,当您直接在 REPL 中逐行运行代码时,它会在不同的上下文中执行。每行都以“单一”模式编译,此优化不可用。>>> 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) ...TrueFalseid(a) = 140737087176016, id(b) = 140737087176080>>> scope['a'], scope['b'](300, 300)>>> id(scope['a']), id(scope['b'])(140737087176016, 140737087176080)