元组拆包与普通赋值有何不同? [复制]
Posted
技术标签:
【中文标题】元组拆包与普通赋值有何不同? [复制]【英文标题】:How does tuple unpacking differ from normal assignment? [duplicate] 【发布时间】:2014-01-10 20:02:54 【问题描述】:从this link我了解到
当前的实现为 -5 到 256 之间的所有整数保留一个整数对象数组,当您在该范围内创建一个 int 时,实际上您只是返回对现有对象的引用
但是当我尝试为我的会话举一些例子时,我发现它在赋值和元组解包方面表现不同。
这里是sn-p:
>>> a,b = 300,300
>>> a is b
True
>>> c = 300
>>> d = 300
>>> c is d
False
【问题讨论】:
没有定义is
对整数的行为方式。您获得的有关今天一种实现的行为方式的任何知识都将是脆弱的。
@Anonymous:“实施定义”比“未定义”更准确,但关于脆弱性的说法仍然成立
Weird Integer Cache inside Python 2.6 的可能副本。不完全相同的问题,但接受的答案(免责声明:我的)显示了在元组的情况下会发生什么,我相信这足以回答您的问题:它是所谓的窥视孔优化器,可以避免重复常量。
谢谢@Bakuriu,找到了一些有趣的解释。
【参考方案1】:
import dis
def testMethod1():
a, b = 300, 300
print dis.dis(testMethod1)
打印:
4 0 LOAD_CONST 2 ((300, 300)) 3 UNPACK_SEQUENCE 2 6 STORE_FAST 0 (a) 9 STORE_FAST 1 (b) 12 LOAD_CONST 0(无) 15 RETURN_VALUE 无
def testMethod2():
a = 300
b = 300
打印:
7 0 LOAD_CONST 1 (300) 3 STORE_FAST 0 (a) 8 6 LOAD_CONST 1 (300) 9 STORE_FAST 1 (b) 12 LOAD_CONST 0(无) 15 RETURN_VALUE 无
所以,它看起来基本相同,但LOAD_CONST
在第一种方法中是一个步骤,在第二种方法中是两个步骤....
编辑
经过一番测试,我发现这两种方法最终都返回False
;但是,仅在一次运行时,即不将方法置于循环中,它们似乎总是返回True
。有时它使用单个引用,有时则不使用。
文档仅说明 -5 到 256 将返回相同的引用;因此,您根本不应该使用is
进行比较(在这种情况下),因为该号码的当前id
对此没有任何保证。
注意:您永远不想使用is
来比较值,因为这不是它的用途,而是比较身份。我的观点是,当您超出定义的范围时,is
的返回值并不总是True
。
【讨论】:
你好 Steve P,我在 osx, python 2.7.2 中测试过 这取决于 Python 实现。分两步加载为释放低级缓存内存提供了更多时间。缓存 [-5, 256] 发生在 Python 代码中,但可以重用不可变对象(如 int)。你不能相信这些缓存。 根据你的最后一段,is
不能用于“比较”。 is
应该用于“身份”。比较 a 和 b 就像说“a 等于 b”。测试身份就像说“a 和 b 是同一件事”
@NoufalIbrahim 我了解is
的作用。我的意思是您不想使用is
进行比较(在这种情况下)。【参考方案2】:
由于 int 是不可变的,Python 可能使用也可能不使用存在对象,如果将以下代码保存到脚本文件中并运行它,它将输出两个 True。
a, b = 300, 300
print a is b
c = 300
d = 300
print c is d
当 Python 编译代码时,它可能会重用所有常量。因为你在 python 会话中输入代码,代码是逐行编译的,Python 不能将所有常量作为一个对象重用。
文档只说-5到256只有一个实例,但没有定义其他人的行为。对于不可变类型,is
和 is not
并不重要,因为您无法修改它们。
【讨论】:
您可以在解释器提示符下模拟这一点,方法是将所有代码放在一个函数中然后运行它(而不是一次运行一个)。以上是关于元组拆包与普通赋值有何不同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章