对象的内存使用
id可以取到python对象的内存地址 以赋值操作为例
可以看到 a 与常量1的地址是一致的。查阅得知
在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。当我们创建多个等于1的引用时,实际上是让所有这些引用指向同一个对象。
可以看到a 和 b 指向同一个变量。 a 和b 均是 1的 一个引用。
可以看到当a 的值发生变化后,a指向的地址发生变化,并且随着数字的复杂度变高,同一个数字指向不同空间。
同样的操作在tuple上 可以看到赋值操作 c = a使得 c,a同时指向一个元组, a的赋值发生变化时,c指向的对象不发生变化,
即python中赋值为 地址的传递 而非值的传递。
在对于a = 2 进行操作时, python没有在原来的地址上进行更改,而是新创建一个2,将a指向了新的2.
那么是不是所有对象的改变都是从新创建对象呢?
测试可知,list, dict对象的改变 并不会创建新的对象,而其内部对象的变化遵照之前的原则。
对list,dict等对象的直接赋值操作则是新创建一个对象
对list dict等对象的间接赋值操作 与 不可变对象一致b = a的操作中实际上将 b,a指向同一个地址,所以b,a能同时改版这个list。
结论:python中 int,float,tuple等不可变对象的改变,并非在原地址上进行更改,而是创建一个新对象,将原来的 引用指向到新的地址。
对于可以改变的对象的内部改变,在其指向的地址进行改变, 所有对象之间的赋值操作 不会占用更多的内存。
可变对象的内部改变,是在原地址上进行更改的,但是对象的整体变化是从新创建新的对象,例如:
可以看到list的切片操作会从新创建一个list对象,赋值操作遵照切换地址的原则。
函数值传递时候,与赋值操作一致,a,x指向同一个对象,当a,x发生内部变化时操作的也是同一个变量,当发生外部变化时x指向新的外部对象,a保持不变。
公共变量
在python工程中经常有使用某文件中的公共变量的情况,经常会出现一些常量丢失的情况,以上述python对象内存的原则分析
运行test2.py得到
1 33522008
33521984
1 33522008
2 33521984
对于不可变对象x, 在进行第一次import操作时,等同于做了一遍函数赋值,虽然 2个x指向同一个obj 但是为不同的内存对象,
当调用f函数将test1 内存中的x改变时,x1指向了新的地址,而x2仍然指向原先的地址,第二次调用import 后 回复正常,
即引用公共不可变对象最好在使用时import,公共不可变对象 只能通过函数的方式改变其值。
例子分析
一点建议
1:涉及到公共变量初始化,以及使用的地方,路径要 保持一致(否则会出现引用非同一个变量的问题)
2:公共变量的修改最好收敛在同一个文件中,并且初始化操作import时初始化,这样做的好处是即使出现意外的路径引用,依然能够正常工作。