Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3多重分配和内存地址_Python_Python 3.x_Multiple Assignment - Fatal编程技术网

Python3多重分配和内存地址

Python3多重分配和内存地址,python,python-3.x,multiple-assignment,Python,Python 3.x,Multiple Assignment,在阅读了和我的问题非常相似的内容后,我仍然无法理解以下行为: a = 257 b = 257 print(a is b) #False a, b = 257, 257 print(a is b) #True 在打印id(a)和id(b)时,我可以看到,在单独的行中分配值的变量具有不同的id,而在多个分配中,两个值具有相同的id: a = 257 b = 257 print(id(a)) #139828809414512 print(id(b)) #139828809414224 a, b =

在阅读了和我的问题非常相似的内容后,我仍然无法理解以下行为:

a = 257
b = 257
print(a is b) #False
a, b = 257, 257
print(a is b) #True
在打印
id(a)
id(b)
时,我可以看到,在单独的行中分配值的变量具有不同的id,而在多个分配中,两个值具有相同的id:

a = 257
b = 257
print(id(a)) #139828809414512
print(id(b)) #139828809414224
a, b = 257, 257
print(id(a)) #139828809414416
print(id(b)) #139828809414416
但不可能通过多次赋值总是创建指向同一id的指针来解释这种行为,因为:

a, b = -1000, -1000  
print(id(a)) #139828809414448
print(id(b)) #139828809414288
是否有明确的规则来解释变量何时获得相同的
id

编辑


相关信息:此问题中的代码是在交互模式(ipython3)下运行的。

任何此类规则都是特定于实现的。例如,CPython为小整数(-5到256)预先分配
int
对象作为性能优化


唯一的一般规则是假设任何文字的使用都将生成一个新对象。

这是因为pythons解释器在加载常量值期间在
解包序列时进行了优化。当python在解包过程中遇到iterable时,它不会多次加载重复的对象,而是保留第一个对象并将所有重复的变量名分配给一个指针(在CPython实现中)。因此,所有变量都将成为对一个对象的相同引用。在python级别,您可以将此行为视为使用字典作为名称空间,而不保留重复的键

换句话说,您的解包相当于以下命令:

a = b = 257
关于负数,在Python2.X中没有任何区别,但在Python3.X中,对于小于-5的数字,python将在解包期间创建新对象:

>>> a, b = -6, -6
>>> a is b
False
>>> a, b = -5, -5
>>> 
>>> a is b
True

这是由于字节码编译器中的不断折叠优化。当字节码编译器编译一批语句时,它会跟踪所看到的常量。此dict自动合并任何等效常量

以下是负责记录和编号常量的例行程序(以及一些相关职责):

在脚本中,所有顶级语句都是一个批处理,因此:

在脚本中,这将打印
True

函数的代码与函数外部的代码分开跟踪其常量,这限制了常量折叠:

a = 257

def f():
    b = 257
    print a is b

f()

,这会打印出
False

数字是
257
,你也可以通过使用更大的整数看到这种行为。我总是忘记确切的范围。不是“将生成”,而是“可能生成”。你的答案如何解释我问题的最后一部分,a,b=-1000,-1000?@isternberg在上一部分中,您已经分别创建了变量,但python3中的负数解包还有另一点,我会尽快更新答案,说明原因。“一个加载常数和两个存储速度”——如果您是正确的,
LOAD\u常量
正在加载一个常量
元组
,该元组包含两个项。我不确定这是如何解释这两个值具有相同ID的(当它们超出python内部整数的正常范围时)!这是完全错误的<代码>解包顺序
与此无关。您将看到相同的加载常数和解包序列行为,但是
a
b
明显不同。您也可以避免优化,而且
UNPACK_SEQUENCE
不会合并常量。@Kasramvd,thx,感谢您告诉我问题中的错误。我修复了它。请查看
[id(I)for I in(10001000)]
:-)注意:行为不一致,因为它根本不重要。如果有任何理由关心两个
257
s是否是同一个对象,那么它将有一个简单、合理的模式。窥视孔优化,与它的工作方式无关,因为它从来都不是你会或应该依赖的。谢谢。我将编辑我的问题以明确它是在交互模式下测试的。那么在python 3中小于
-5
的整数呢?例如
a,b=-6,-6
@Kasramvd:编译器将
-6
编译成
加载常量和
一元负数
;有一个负责将其转换为加载一个
-6
加载常量。该优化实际上没有使用dict.@user2357112,但我在C代码中没有发现小于-5的限制(这是否与负数以2的补码的一种变体表示有关,它给人一种无限符号位串向左延伸的错觉?@Kasramvd:
-5
由另一种优化处理,即小整数池。所有
-5
都是相同的对象,无论您如何或在何处创建它们。
>>> a = 1000
>>> b = 1000
>>> a is b
False
>>> a = 1000; b = 1000 # 1 batch
>>> a is b
True
a = 257
b = 257
print a is b
a = 257

def f():
    b = 257
    print a is b

f()