python可变、不可变数据类型
用于记录python数据类型
python我个人常用的数据就是数字、字符串、元组、列表、集合、字典,分为可变类型和不可变类型。
一、什么是可变和不可变的数据类型?
可变就是说在相同内存地址的内容可以发生改变,反之,不可变类型就是相同地址的内容不能被修改。
二、不可变类型
1.数字
#数字
a=1.0
print(id(a), type(a))
a=2.0
print(id(a), type(a))
输出:
2633529434384 <class 'float'>
2633566302832 <class 'float'>
本以为数字相同变量,重新赋值后还在相同地方,其实他已经修改了地址了。。不过不影响使用就是了。
2.字符
#字符
a="a"
print(id(a), type(a))
a="b"
print(id(a), type(a))
输出:
2633529434384 <class 'float'>
2633566302832 <class 'float'>
字符也是另外的地址了
3.元组
#元组
#元组可以当作是没有类型的数组,不可被改变
a=(1,2)
print(id(a), type(a))
a=(3,4)
print(id(a), type(a))
a[0]=0
#报错,不能被重新赋值
输出:
2633566244032 <class 'tuple'>
2633566657280 <class 'tuple'>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In [7], line 7
5 a=(3,4)
6 print(id(a), type(a))
----> 7 a[0]=0
TypeError: 'tuple' object does not support item assignment
字符也是另外的地址了
三、可变类型
4.列表
##列表
#元组用小括号
a=(1,2)
#列表用中括号
b=[3,2]
print(b)
#重新赋值
#a[0]=3 #出错
b[0]=1 #可运行
print(b)
输出:
[3, 2]
[1, 2]
但是元组和列表使用numpy转成数据就相同了。我们在正常使用中通常是用到numpy的,所以是没问题的。
#转成numpy就一样了
#元组转numpy数组
import numpy as np
c=np.array(a,dtype=np.uint8)
d=np.array(b,dtype=np.uint8)
print("a:",a)
print("b:",b)
print("c:",c)
print("d:",d)
print(c==d)
输出:
a: (1, 2)
b: [1, 2]
c: [1 2]
d: [1 2]
[ True True]
需要注意的点
由于列表是可变类型,因此如果使用浅拷贝会改变原始值、目标值。
b=[3,2] #原始值
print(b)
c=b #浅拷贝 C为目标值
c[0]=1
print(b) #目标值改变导致原始值改变
print("//")
print(c)
b[0]=4
print(c) #原始值改变导致目标值改变
输出:
[3, 2]
[1, 2]
//
[1, 2]
[4, 2]
若不想改变可用深拷贝
##深拷贝互不影响
import copy
b=[3,2] #原始值
print(b)
c=copy.deepcopy(b) #深拷贝 C为目标值
c[0]=1
print(b) #目标值改变,不影响原始值
print("//")
print(c)
b[0]=4
print(c) #原始值改变,不影响目标值
输出:
[3, 2]
[3, 2]
//
[1, 2]
[1, 2]
5.集合
# 集合
set1 = {1, 2, 3, '123'}
print("集合:", set1, "内存地址:", id(set1), "\t", "数据类型:", type(set1), "\t")
# 给set1删除一个元素
set1.remove(2)
print("集合:", set1, "内存地址:", id(set1), "\t", "数据类型:", type(set1), "\t")
输出:
集合: {'123', 1, 2, 3} 内存地址: 2635583510784 数据类型: <class 'set'>
集合: {'123', 1, 3} 内存地址: 2635583510784 数据类型: <class 'set'>
5.字典
#字典
#采用键值对(key-value)的形式存储数据
dict1 = {'name': 'abc', 'age': 18}
print("字典:", dict1, "内存地址:", id(dict1), "数据类型:", type(dict1))
#重新赋值
dict1['sex'] = 'man'
print("字典:", dict1, "内存地址:", id(dict1), "数据类型:", type(dict1))
注意事项与列表相同
输出:
字典: {'name': 'abc', 'age': 18} 内存地址: 2635718986560 数据类型: <class 'dict'>
字典: {'name': 'abc', 'age': 18, 'sex': 'man'} 内存地址: 2635718986560 数据类型: <class 'dict'>
注意事项与列表相同
6.补充 -深拷贝和浅拷贝
深拷贝:对原对象的地址的拷贝,新拷贝了一份与原对象不同的地址的对象,修改对象中的任何值,都不会改变深拷贝的对象的值。
浅拷贝:对原对象的值的拷贝,地址仍是一个指针指向原对象的地址,浅拷贝或者原对象的值发生变化,那原对象和浅拷贝对象的值都会随着被改变。
浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用
深拷贝(深度克隆):不仅复制对象的基本类,同时也复制原对象的对象,完全是新对象产生的
copy.copy #浅拷贝
copy.deepcopy #深拷贝
总结
个人学习中想要记录的一些东西,
不可变数据类型中的数字和字符,对日常使用无影响,元组只要记住不可变就行,因为不可被串改,因此可作为记录使用。若想使用能改变的就用列表或转成numpy数组。
可变数据类型记住浅拷贝的时候,原始值和目标值改变一个,另外一个也会发生改变。