元组不可变,你真的确定吗?有了列表,元组存在的意义又是什么?【一文搞懂】

本文探讨了Python中元组的特性,尤其是其不可变性。虽然通常认为元组不可变,但通过例子展示了如何在元组内改变可变类型如字典的值。元组存在的原因包括性能优势——占用空间小且能利用Python的内存缓存,作为字典键的合法性,以及工厂函数具名元组的应用。文章强调了元组在记录和优化程序性能上的价值。
摘要由CSDN通过智能技术生成

一、前言

学过python的小伙伴都知道,python有一种数据类型叫元组,它与列表很相似!

而元组与列表最让我们熟知的区别就在于元组不可变!

类似下面的代码执行的话会直接报错:

a=(1,2)
a[1]=3
print(a)

报错信息
在这里插入图片描述


但元组真的是不可改变的吗?

下面的这段代码可能会让你心生疑惑

我们定义一个元组它的值为{1,{'key':1}},然后改变它的值:

a = (1, {'key': 1})
a[1]['key'] = 2
print(a)

输出结果:
在这里插入图片描述


在这里插入图片描述

这结果不是改变了吗!!!

那为啥都说元组不可变!!!

二、分析

其实说元组不可变实际上没有错,它指的是元组里元素的内存地址不可改变

我们把改变前和改变后的元素id打印出来,会发现他们是一样的

a = (1, {'key': 1})
print('改变之前的元素id', id(a[1]))
a[1]['key'] = 2
print('改变之后的元素id', id(a[1]))

输出结果
在这里插入图片描述


至于为什么修改了元素的值,元素的内存地址未改变。是因为该元素的类型是dict,而dict又是一个可变类型,仅仅改变里面的值的话不会改变其内存地址(详情可参考:python不可变类型和可变类型讲解)

所以在元组中修改它的值是可以的。


三、为什么有了列表还要有不可修改的元组呢?

这里从三个方面做解答

1.元组性能优于列表

元组占用的空间比列表少

我们仅仅定义了6个相同的元素,分配的空间大小就相差了快1倍!

a = [1, 2, 3, 4, 5, 6]
print('列表的空间大小为:', a.__sizeof__())
b = (1, 2, 3, 4, 5, 6)
print('元组的空间大小为:', b.__sizeof__())

输出结果
在这里插入图片描述


另外,在Python的垃圾回收机制下,如果一些变量不再使用了,Python会回收它们所占用的内存并返还给操作系统,以便让其他变量或其他应用使用这部分内存。

但是对于一些静态变量,比如元组,当它不被使用并且占用空间不大时,Python 会暂时缓存这部分内存。这样,下次我们再创建同样大小的元组时,Python 就可以不用再向操作系统发出请求,去寻找内存,而是可以直接分配之前缓存的内存空间,这样就能大大加快程序的运行速度!

2.元组可以作为字典key而列表不行

输入下面的代码执行的话会直接报错!

a = [1, 2]
b={a:1}

输出结果
在这里插入图片描述
而如果用元组作为字典的key的话则不会报错!

a = (1, 2)
b={a:1}
print(b)

输出结果
在这里插入图片描述
准确的说,所有不可变类型都可以,而类似list 的可变类型则不可以!!

3.工厂函数

这里就要提到python的一个工厂函数具名元组(namedtuple)

具名元组是 python 标准库 collections 中的工厂函数。它接受两个参数,第一个参数表示类的名称,第二个参数是类的字段名。后者可以是可迭代对象,也可以是空格隔开的字符串。然后,我们通过一串参数的形式将参数传递到构造函数中。这样,我们既可以通过字段名访问元素,也可以用索引访问元素。

只讲具名元组,可能不太好理解。如果称之为带字段名的记录,你可能就清楚了。


现在我们创建一个人员的基础信息类People

它有三个属性:姓名name、性别sex、年龄age

现在创建一个姓名叫张三,22岁的小伙儿,再打印出他的信息

from collections import namedtuple
People = namedtuple('People', 'name sex age')
# 存放在对应字段里的数据要以一串参数的形式传入到构造函数中
person = People('张三', '男', 22)
print(person)
print(person.name)  # 通过字段名获取一个字段的值
print(person._fields)  # 通过fields来获取它有哪些属性

输出结果
在这里插入图片描述


还可以直接将具名元组转化为orderdict(在上述代码末尾加入下列代码)

person_dict = person._asdict()
print(person_dict)

输出结果
在这里插入图片描述


四、总结

元组是一种很强大的可以当作记录来用的数据类型,这才是他存在的价值和意义所在!

只是作为一个不可变的列表更被大家所熟知而已。

分享暂时到这里,小伙伴们点赞、收藏、评论是对我最大的支持!!


往期博文

Python通过字符串来执行函数甚至代码!这么顶的操作快来了解下!

Pycharm用着卡还收费!何不试试VSCode!一文学会VSCode使用python

  • 137
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 95
    评论
评论 95
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曲鸟

不要打赏,没必要!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值