元组拆包与普通赋值有何不同? [复制]

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只有一个实例,但没有定义其他人的行为。对于不可变类型,isis not 并不重要,因为您无法修改它们。

【讨论】:

您可以在解释器提示符下模拟这一点,方法是将所有代码放在一个函数中然后运行它(而不是一次运行一个)。

以上是关于元组拆包与普通赋值有何不同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

元组拆包具名元祖

元组拆包顺序更改分配的值

什么是方案相当于元组拆包?

元组--补充

元组--补充

流畅的python和cookbook学习笔记