Python 之何为可变序列和不可变序列

可变序列(可变类型)

所谓可变序列就内存中的数据可以被修改。也就是说,我们可以对可变序列进行增、删、改操作,并且执行完这些操作后,对象的地址不会发生更改(即不会开辟新的内存空间)。(对象的内存地址可以通过内置函数 id() 来查看)

常见的可变序列有三种:列表(set)、字典(dict)、集合(set)。

我们对可变类型的数据进行增、删、改操作时,是通过方法来实现的。而如果对一个可变类型的变量,赋值一个新的数据,它的引用会修改,也就是变量不再对之前的数据引用,而是对新赋值的数据引用

1)列表

列表是有序的可变序列,通过调用方法对其进行增删改操作,它的内存地址不会发生更改。但如果对一个可变类型的变量重新赋值,变量的引用会被修改,这时它指向新赋值的数据(就相当于把标签撕下来贴到另一个盒子上面)。

lst = [10,20,30,40]
print(f'原列表是:{lst} 内存地址:{id(lst)}')

# 增加元素
lst.append(666)
print(f'增加元素后的列表:{lst} 内存地址:{id(lst)}')

# 删除元素
lst.pop(0)
lst.remove(20)
print(f'删除元素后的列表:{lst} 内存地址:{id(lst)}')

# 修改元素
lst[0] = 888
print(f'修改元素后的列表:{lst} 内存地址:{id(lst)}')

lst.clear()
print(f'清空列表元素后的列表:{lst} 内存地址:{id(lst)}')

# 如果对一个可变类型的变量(如lst)重新赋值,它的引用会被修改,这是lst不再指向原列表,而是指向新赋值的数据
lst = []
print(f'重新赋值后的列表:{lst} 内存地址:{id(lst)}')
图片[1]-Python 之何为可变序列和不可变序列-尤尤'blog
图片[2]-Python 之何为可变序列和不可变序列-尤尤'blog
内存示意图

2)字典

字典是无序的可变序列,但注意:字典中的键必须是不可变对象,值可以是任何数据类型。

dct = {'name':'张三', 'age':22, 'gender':'male'}
print(f'原字典是:{dct} 内存地址:{id(dct)}')

# 增加元素
dct['phone'] = '13456789000'
print(f'增加元素后的字典:{dct} 内存地址:{id(dct)}')
# 删除元素
dct.pop('age')
print(f'删除元素后的子弹:{dct} 内存地址:{id(dct)}')
# 修改元素
dct['gender'] = 'female'
print(f'修改元素后的字典:{dct} 内存地址:{id(dct)}')
dct.clear()
print(f'清空字典元素后的字典:{dct} 内存地址:{id(dct)}')

# 如果对一个可变类型的变量(如lst)重新赋值,它的引用会被修改,这是lst不再指向原列表,而是指向新赋值的数据
dct = {}
print(f'重新赋值后的字典:{dct} 内存地址:{id(dct)}')
图片[3]-Python 之何为可变序列和不可变序列-尤尤'blog

不可变序列(不可变类型)

不可变序列就是内存中的数据不能被修改,即没有增、删、改操作。

不可变序列一旦进行了增、删、改操作,就会开辟一块新的内存空间(id 发生了改变)来存储改变后的数据。

常见的不可变序列有三种:数字类型(int、bool、float、complex)、字符串(str)、元组(tuple)。

例如:

>>> a = 123
>>> id(a)
1737568620592
>>> id(123)
1737568620592
>>> a = 'python'
>>> id(a)
1737572407984
>>> id('python')
1737572407984
图片[4]-Python 之何为可变序列和不可变序列-尤尤'blog

在 Python 中,数据和变量是分开存储的,数据是存储在内存的某一个位置中,而变量中保存的是数据在内存中的地址。就相当于:我们将数据放到一个盒子(内存空间)中,再拿一个变量 a 当做是标签贴到盒子上面。

在上面的代码中 123 是整型,是一个不可变类型。当 a = ‘python’ 时,就相当于将 a 这个标签撕下来,贴到装 ‘python’ 的盒子上面。这时的 a 仅仅是对新赋值值的 ‘python’ 的引用。而 123 则被回收了。

图片[5]-Python 之何为可变序列和不可变序列-尤尤'blog

这就是不可变类型,它们一旦定义,也就是给它在内存中分配了内存空间,里面存放了数据,就不允许修改了。如果对它进行了增、删、改操作,它的内存地址就发生了改变,也就是将这个新数据存储在一个新的内存空间中。这个时候变量是对新赋值的数据引用。而原来的数据被垃圾回收机制回收了。

1)数字类型(int、bool、float、complex)

a = 123
print(f'a 的id是:{id(a)},123 的id是:{id(123)}')

# 给a赋值一个新的数据,这时a是对新赋值的数据100的引用
a = 100
print(f'a 的id是:{id(a)},123 的id是:{id(100)}')

b = 1.3
print(f'b 的id是:{id(b)},1.3 的id是:{id(1.3)}')
b = 5.2
print(f'a 的id是:{id(b)},5.2 的id是:{id(5.2)}')
图片[6]-Python 之何为可变序列和不可变序列-尤尤'blog

2)字符串(str)

s = 'hello'
print(s,' 的id是:',id(s))

# 修改字符串
new = s.replace('l','a')

# s中的内容没有改变,而是新开辟了一块内存空间用于存放替换后的字符串
print(s,' 的id是:',id(s))

print(new,' 的id是:',id(new))
图片[7]-Python 之何为可变序列和不可变序列-尤尤'blog

3)元组(tuple)

元组是一个有序的不可变序列。我们不能对其中的元素进行修改、删除操作。

在元组中,如果元素本身是不可变类型,就不能再引用其他数据类型了;如果元素本身是可变序列,那么该元素的引用不能改变,其中的数据却是可以改变的。

t = (10,20,[666,888],30)

print(t,'的内存地址id是:',id(t))

# 元组是有序的不可变序列,所以可以根据下标来访问元素
print(t[1],'的内存地址是:',id(t[1]))

# t[1] = 20,该元素是不可变类型,不能修改它的引用
# t[1] = 200  # TypeError: 'tuple' object does not support item assignment

print(t[2],'的更改数据前的内存地址是:',id(t[2]))
# t[2] = [666,888] 是一个列表,是有序的可变序列,我们调用它的方法对其进行增加、修改、删除操作
t[2].append(999)
print('增加元素后:',t[2],id(t[2]))

t[2][0] = 111
print('修改元素后:',t[2],id(t[2]))

t[2].remove(888)
print('删除元素后:',t[2],id(t[2]))
图片[8]-Python 之何为可变序列和不可变序列-尤尤'blog
© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容