在学习对象的易变性时,我在python shell中玩了一会儿。
我发现了一些奇怪的东西:
>>> x=5.0
>>> id(x)
48840312
>>> id(5.0)
48840296
>>> x=x+3.0
>>> id(x) # why did x (now 8.0) keep the same id as 5.0?
48840296
>>> id(5.0)
36582128
>>> id(5.0)
48840344
为什么在语句
x=x+3.0
之后重用5.0的id? 最佳答案
从根本上说,你的问题的答案是“打电话给数字会给你带来不可预测的结果”。这是因为不像Java这样的语言,在Java中,原语实际上是它们在内存中的值,Python中的“原语”仍然是对象,并且不能保证每次都会使用完全相同的对象,而仅仅是功能上等价的对象。
CPython缓存-5到256之间的整数值以提高效率(确保对id()
的调用始终是相同的),因为这些值是常用的,并且可以有效地缓存,但是关于语言的任何内容都不需要这样做,其他实现可能会选择不这样做。
无论何时用Python编写双字文本,都要求解释器将字符串转换为有效的数字对象。如果可以,Python将重用现有的对象,但是如果它不能很容易地确定一个对象是否已经退出,它将简单地创建一个新的对象。
这并不是说Python中的数字是可变的——它们不是可变的,Python中的任何数字实例,比如id()
,在创建后都不能被用户更改。然而,就解释器而言,构造同一个数的多个实例并没有错。
表示5.0
的对象被重用为x = 5.0
值的具体示例是一个实现细节。如果CPython认为合适的话,它可以重用数值对象,包括整数和浮点数,以避免构建一个全新对象的代价高昂的活动。不过,我强调,这是一个实现细节;某些情况下完全可能不会显示这种行为,而且CPython可以随时更改其数字处理逻辑,使其不再以这种方式运行。你应该避免编写任何依赖于这种怪癖的代码。
正如eryksun指出的,另一种选择是,您偶然发现一个对象被垃圾收集并在同一位置被替换。从用户的角度来看,这两种情况没有区别,这就强调了x += 3.0
不应该用于“原语”。