>>> a = 'abc'
>>> id(a)
4549707624
>>> a = a + 'def'
>>> a
'abcdef'
>>> id(a)
4550507744
>>> a = a.strip('def')
>>> a
'abc'
>>> id(a)
4550507800
可以看出,当string类型的数据经过一些拼接操作后,值虽然与初始值相同,但id却发生了变化。
>>> a = 123
>>> id(a)
4405328880
>>> a = a + a -a + a - a
>>> a
123
>>> id(a)
4405328880
>>> a = int(str(a))
>>> id(a)
4405328880
>>> import math
>>> a = int(math.sqrt(a ** 2))
>>> a
123
>>> id(a)
4405328880
>>>
>>>
>>> b= 999
>>> id(b)
4407590800
>>> b = b + b - b + b - b
>>> id(b)
4407590832
从上例看到,对于变量a,经过简单和复杂的一系列变化,内存地址未变化,但对于b,只加减了一下,内存地址就变化了一下。听朋友说,在python中,为了节省内存,对于比较小的数字,如果已经有相同值存在于内存中,就继续使用原地址,比较大的数字就会新建内存区域。上述代码貌似印证了这一点,但多大算大?多小算小呢?一个个试太麻烦,不如写个函数文件来试试。
import math
#测试不可变类型是否始终占用同一内存地址
#integer
def test_integer():
x = 0
while True:
init_id = id(x)
final_id = id(int(math.sqrt(x ** 2)))
if init_id != final_id:
print('x = %s, using different id: %s and %s' % (x, init_id,final_id))
break
print('x = %s, using same id: %s' % (x, init_id))
x += 1
return
test_integer()
#
输出结果如下:
...#(省略部分输出)
x = 235, using same id: 4544678384
x = 236, using same id: 4544678416
x = 237, using same id: 4544678448
x = 238, using same id: 4544678480
x = 239, using same id: 4544678512
x = 240, using same id: 4544678544
x = 241, using same id: 4544678576
x = 242, using same id: 4544678608
x = 243, using same id: 4544678640
x = 244, using same id: 4544678672
x = 245, using same id: 4544678704
x = 246, using same id: 4544678736
x = 247, using same id: 4544678768
x = 248, using same id: 4544678800
x = 249, using same id: 4544678832
x = 250, using same id: 4544678864
x = 251, using same id: 4544678896
x = 252, using same id: 4544678928
x = 253, using same id: 4544678960
x = 254, using same id: 4544678992
x = 255, using same id: 4544679024
x = 256, using same id: 4544679056
x = 257, using different id: 4546928240 and 4546926128
临界值找到了,256,2的8次方。我猜想在内部存储方式是类似1 0000 0000的二进制,比这个大的都一律重新使用新内存地址,比这个小的(含)就先检查一下内存里有没有相同的值已经存在,如果有就用已经存在的内存地址,省得新建了。
>>> a = 1.0
>>> id(a)
4425023728
>>> a = a + a - a
>>> id(a)
4425023608
>>> a = a + a - a
>>> id(a)
4425023872
>>> a = a + a - a
>>> id(a)
4425023728
>>> a = a + a - a
>>> id(a)
4425023608
>>> a = a + a - a
>>> id(a)
4425023872
>>> a = a + 1 -1
>>> id(a)
4425023728
>>> a = a + 1 -1
>>> id(a)
4425023608
>>> a = a + 1 -1
>>> id(a)
4425023872
>>> a = a + 1 -1
>>> id(a)
4425023728
>>> a = a + 1.1
>>> a = a - 1.1
>>> id(a)
4425023728
>>> a = a + 1.1
>>> a = a - 1.1
>>> id(a)
4425023728
>>> a = a + 1.1
>>> a = a - 1.1
>>> id(a)
4425023728
>>> import math
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425024064
>>> a
1.0
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425024088
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425023728
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425024064
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425024088
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425023728
>>> a = math.sqrt(a ** 2)
>>> id(a)
4425024064
>>> a = a + a
>>> a = a / 2
>>> id(a)
4425024064
>>> a = a ** 2
>>> a = math.sqrt(a)
>>> id(a)
4425024064
>>> a
1.0
>>> a = a * 5
>>> a = a - 2.0
>>> a = a + 2
>>> a = a / 5
>>> id(a)
4425024160
>>> a = float(int(a))
>>> id(a)
4425024064
>>> a = float(int(a))
>>> id(a)
4425024160
>>> a = float(int(a))
>>> id(a)
4425024064
>>> a = float(int(a))
>>> id(a)
4425024160
>>> b = 1
>>> c = float(b)
>>> id(c)
4425024064
>>>
Float数据的表现好像有点规律,比如在同一赋值语句中执行简单的完全互逆操作时,有值相等的2个或3个id在循环,当将互逆语句分开执行时,id则保持不变或者2个id循环。很难得出结论,不作深入讨论。
在Python中,对于不可变类型,相同的值不一定引用自相同的内存,也就是某一个值可能存在于多个地址中。