Python的值类型(不可变类型),引用类型(可变类型) | 深浅拷贝 | 指针
首先值类型和引用类型指的都是对象的类型
值类型:
int float str tuple bool
引用类型:
list dict set
变量:
Python中的变量都是指针,而指针实际上就是存放变量地址的变量
对象:
在 Python 中一切都是对象,所有Python对象都拥有三个特性:身份、类型、值。
身份:每个对象都有一个唯一的身份标识,任何对象的身份可以使用内建函数id()来得到
类型:对象的类型决定了该对象可以保存什么类型的值,可以进行什么样的操作,以及遵循什么样的规则。可以使用 type()函数查看python对象的类型。type()返回的是对象而不是简单的字符串。
值:对象表示的数据。
值类型为什么被称为不可变类型
x = 1
y = 1
print(id(x),'-x在内存上的位置') #8791163524128 -x在内存上的位置
print(id(y),'-y在内存上的位置') #8791163524128 -y在内存上的位置
x = 2
y = 2
print(id(x),'-x在内存上的位置') #8791163524160-x在内存上的位置
print(id(y),'-x在内存上的位置') #8791163524160-y在内存上的位置
对不可变类型我的理解是,比如x=1在内存位置8791163524128上的不可变类型的对象的值一旦确定,在被垃圾回收之前,这个位置上的对象的值就不能有任何改变(这点和可变类型就有差别了),如果要改变x指向的值,只能指向在内存其他位置上的对象。
值相同的不可变类型的对象在内存上的地址是一样的。正如上面变量x和y所指向的对象都是数字1,所以他们指向的地址都是一样的
引用类型为什么被称为可变类型
x = [1,2,3]
y = [1,2,3]
print(id(x),'-x在内存上的位置') #30171720 -x在内存上的位置
print(id(y),'-y在内存上的位置') #30171784 -y在内存上的位置
x.append(4)
print(id(x),'-x在内存上的位置') #30171720 -x在内存上的位置
对可变类型我的理解是,比如说在例子中,在内存位置30171720上的对象的值是可以被修改的,值从[1,2,3]->[1,2,3,4],而内存位置可以依然不变
还值得注意的一点是,对于可变类型,有相同的值的对象在内存位置是可以不同的,在例子中虽然x和y都有相同的值[1,2,3],但是该值在内存上的位置却是不同的,这点和值类型是不同的。
对于不可变类型需要注意的点(为什么元组中的列表是可以被改变的)
x = 2
yuanzu = (1,2)
print(id(yuanzu[1]),'-元组中的2') #8791159460928 -元组中的2
print(id(2),'-数字2') #8791159460928 -数字2
print(id(x),'-被2赋值的x') #8791159460928 -被2赋值的x
从上面的代码可以发现,数字2、元组中的数字2和x所指向的内存位置是一样的,那么就可以说明元组储存的元素和x一样,都是储存地址。所以结合上面对可变类型的分析,改列表地址上的对象是可以被改变的,于是乎改元组中的列表中的值就是可以被改变的
yuanzu = (1,2,[1,2])
print(id(yuanzu),'-元组的位置') # 36022096 -元组的位置
print(id(yuanzu[2]),'-列表的位置') # 30499400 -列表的位置
print('----------------------')
yuanzu[2].append(3)
print(id(yuanzu),'-元组的位置') # 36022096 -元组的位置
print(id(yuanzu[2]),'-列表的位置') # 30499400 -列表的位置
可见即使改了元组中的列表中的值,元组和列表在内存中的位置都没有发生改变
浅拷贝
使用切片[:]操作也会导致浅拷贝