内存管理方式
引用计数
对象被创建时就创建了一个引用计数,当对象不再需要时,引用计数为0,该对象被垃圾回收
可以使用
sys.getrefcount()
获取对象的当前引用计数,不可变数据对象是共享内存的,以节约空间
垃圾回收
内存中有不再使用的部分时,垃圾收集器就会清理掉
- 引用计数为0
- 相互引用的两个对象,因为此时两对象其他引用已为0
内存池
管理小块内存的申请和释放,减少内存碎片,提高效率
预先在内存中申请一定数量、大小相等的内存块备用,有新的内存需求时就从内存池中分配内存给这个需求,不够了再申请新的内存
不可变对象
字符串为不可变对象,不会单独申请内存空间。改变源对象的值,其内存空间会发生改变,但引用对象的值和内存空间都不会发生改变
对于不可变对象,同一个代码块中,若是值相同的对象,是不会重复创建的,会直接引用已存在的对象
import copy
import sys
a = '123'
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
a = '234'
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
可变对象
赋值
对象引用,指向同一个对象
浅拷贝
不需要导入copy模块,不过copy模块中也有copy()
a.copy()
拷贝父对象,不拷贝子对象,子对象会随之变化
深拷贝
需要导入copy模块
copy.deepcopy(a)
拷贝父对象和子对象,源对象的变化与深拷贝对象无关
实例
import copy
import sys
a = ['123']
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
#这里相当于创建了一个新的对象a
a = ['234']
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
import copy
import sys
a = ['123', '456']
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
# 修改父对象
# b是对象引用,所以值和内存同a
# c是浅拷贝,父对象不受影响,所以值不变
# d是深拷贝,父对象和子对象都不受影响
a[1] = '789'
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
import copy
import sys
a = ['123', ['123', '456']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')
# 修改子对象
# 原因同上例
a[1][0] = ['789']
print('a:', a, id(a))
print('b:', b, id(b))
print('c:', c, id(c))
print('d:', d, id(d), '\n')