在 Python 中,变量都是指针;指针的内存空间与数据类型无关,其内存空间保存了指向数据的内存地址。
注意:在 C 中,当定义一个变量后,编译器就一定会给该变量分配内存,后续对该变量的读写是通过该内存地址实现的;而在 Python 中,只会给对象分配内存。
在 Python 中,一切皆对象,主要由以下部分组成:
identity(ID):标识对象的“内存地址”,可使用 id(obj) 获取(唯一标识)
type(类型):标识对象的“类型”,可使用 type(obj) 获取
value(值):标识对象的“值”,可使用 print(obj) 获取
注意:对象的本质是一个内存块。
注意:变量无类型,对象有类型;变量位于栈内存,对象位于堆内存。
可变对象:list(列表)、set(集合)、dict(字典),具有以下特性:
不可变对象:bool(布尔)、int(整数)、float(浮点数)、str(字符串)、tuple(元组)、frozenset(不可变集合),具有以下特性:
声明对象时,对于可变对象,会分配新的空间;对于不可变对象,相同值存储于同一空间中。
(1)可变对象
a=[1, 5]
b=[1, 5]
print(id(a))
print(id(b))
2293112497344
2293112519488
(2)不可变对象
a=1
b=1
print(id(a))
print(id(b))
2293005642032
2293005642032
修改值时,对于可变对象,修改值会修改当前空间的值,不会重新分配空间;对于不可变对象,修改值会分配新的空间。
(1)可变对象:
a=[1,2,5]
print(id(a))
a.append(8)
print(id(a))
print(a)
1914135759360
1914135759360
[1, 2, 5, 8]
(2)不可变对象:
a=1
b = a+1 # 如果是a = a+1,则新的a会覆盖旧的a
print(id(a))
print(a)
print(id(b))
print(b)
2183033481520
1
2183033481552
2
直接赋值:对象的引用。
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。重新分配一块内存,存储原对象的父对象,原对象内部的子对象依然是引用原对象的。
深拷贝(deepcopy): 完全拷贝了父对象及其子对象。重新分配一块内存,将原对象中的元素,以递归的方式复制到新对象,因此新对象和原对象没有任何关联。
(1)直接赋值
b = a: 赋值引用,a 和 b 都指向同一个对象。
(2)浅拷贝
b = a.copy():浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。
(3)深拷贝
b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
实例:
import copy
a = [1, 2, 3, 4, ['a', 'b']] # 原始对象
b = a # 赋值,传对象的引用
c = copy.copy(a) # 对象拷贝,浅拷贝
d = copy.deepcopy(a) # 对象拷贝,深拷贝
a.append(5) # 修改对象a
a[4].append('c') # 修改对象a中的['a', 'b']数组对象
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )
# 结果
('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
('d = ', [1, 2, 3, 4, ['a', 'b']])
引用文章:
http://t.csdn.cn/5kqR2
https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html