前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >#抬抬小手学Python# 列表与元组那些事儿【附源码】

#抬抬小手学Python# 列表与元组那些事儿【附源码】

原创
作者头像
查理不是猹
发布2021-12-30 10:10:41
2540
发布2021-12-30 10:10:41
举报
文章被收录于专栏:查理不是猹的Python专栏

一、列表与元组那些事儿

1. 列表和元组为何要总放在一起

列表和元组在基础篇已经好好的研究了基础用法,你应该保留一个基本印象就是列表和元组,就是一个可以放置任意数据类型的有序集合,或者当成一个容器也可以。

它们两个最直接的区别就是,列表长度大小不固定,可变,元组长度大小固定,不可变。

在很多地方,会把这种区别叫做动态静态

这里最常见的一个错误就是给元组赋值或者修改值了,错误提示如下,出现了要知道原因是啥?

代码语言:txt
复制
TypeError: 'tuple' object does not support item assignment

如何去给元组增加数据呢,我想你应该也比较清楚了,就是新创建一个元组,把新的数据和旧的数据一拼接,搞定。

代码语言:txt
复制
# 梦想橡皮擦 专用的反爬虫注释
my_old_tuple = (1, 2, "a", "b")
my_new_tuple = ("c", "d")

my_tuple = my_old_tuple+my_new_tuple
print(my_tuple)

对于基础部分,还有要注意的就是,元组如果只有一个元素,一定要这么写 (1,) ,逗号不要遗漏,遗漏了括号里面是啥数据类型,最后得到的就是那个数据类型的数据了。

1.1 列表和元组的切片

列表和元组都是有序的,有序就能切片,而切片记住是顾头不顾尾的操作,例如下述代码。

代码语言:txt
复制
my_tuple = my_old_tuple+my_new_tuple
print(my_tuple[1:3])

在刚学习切片的时候,一个比较常见的错误如下,该错误产生的原因是,[] 中括号里面的 : 写成其他符号了。

代码语言:txt
复制
TypeError: tuple indices must be integers or slices, not tuple

1.2 负数索引与二者相互转换

列表与切片二者都支持负数索引取值,但是需要知道负数索引是从 -1 开始的,为啥?自己琢磨。

小声嘀咕:还不是因为 0 只有一个

二者也可以互相转换,转换应用的是内置的函数 listtuple,顺着函数学习下去,列表与元组都有一些可以应用的内置函数,这部分在滚雪球第一遍学习的时候,咱已经都搞定了,很简单的知识点。

1.3 列表与元组的存储方式

运行下述代码查看运行结果,列表与元组元素数目保持一致。

代码语言:txt
复制
my_list = ["a", "b", "c"]
print(my_list.__sizeof__())

my_tuple = ("a", "b", "c")
print(my_tuple.__sizeof__())

输出的结果存在差异,相同元素数据的列表与元组,系统给列表分配的空间要大一些

代码语言:txt
复制
64
48

第一个知识点是 __sizeof__(): 表示的打印系统分配空间的大小。

接下来我们对其进行一下基本的测试,从列表检测系统分配是如何进行空间分配的。

代码语言:txt
复制
my_list = []
print("初始化大小",my_list.__sizeof__())

my_list.append("a")
print("追加1个元素之后的大小",my_list.__sizeof__())

my_list.append("b")
print("追加2个元素之后的大小",my_list.__sizeof__())

my_list.append("c")
print("追加3个元素之后的大小",my_list.__sizeof__())

my_list.append("d")
print("追加4个元素之后的大小",my_list.__sizeof__())

my_list.append("e")
print("追加5个元素之后的大小",my_list.__sizeof__())

运行结果为:

代码语言:txt
复制
初始化大小 40
追加1个元素之后的大小 72
追加2个元素之后的大小 72
追加3个元素之后的大小 72
追加4个元素之后的大小 72
追加5个元素之后的大小 104

增加一个元素之后,大小变成了 72,然后连续增加 4 个元素,系统分配的大小都没有变化,地 5 个元素,又增加了 32 字节空间,这样已经可以得到结论了:

列表会一次性的增加 4 个元素的空间,当空间使用完毕之后,才会继续增加。

上述代码的原理:

列表从本质上看,是一个动态的数组,列表中并不是存储的真实数据,而是每个元素在内存中的地址(引用),因为列表存储是元素的引用这个特性,所以引用占用的内存空间是相同的,也就是 8 个字节,并且这样可以存储不同类型的数据。

在 64 位的操作系统中,地址占用 8 个字节,如果你的电脑是 32 位,那地址占用的是 4 个字节,注意下即可。

1.4 列表和元组的应用场景

简单来说,元组用在固定元素内容的数据上,列表用在可变的数据上,在希望记忆的简单一些,可以直接记成如果只需要 2、3 个元素,就使用 tuple,元素在多就使用 namedtuple,它是一个函数。

使用 namedtuple 需要先进行导入。

代码语言:txt
复制
from collections import namedtuple
help(namedtuple)

函数原型如下:

代码语言:txt
复制
namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
# Returns a new subclass of tuple with named fields.

先写一段测试代码:

代码语言:txt
复制
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x)
print(p.y)

前面两个参数需要简单学习一下。

  • typename:字符串类型的参数,这个参数理解起来比较绕,贴一下官方的解释,namedtuple() 会根据这个 typename, 创建一个子类类名返回出去,例如上文的测试代码中的 Point,创建好的类名称就是 Point ,第二个参数就是以后的类属性了。
  • field_names:用于为创建的元组的每个元素命名,可以传入列表或者元组,例如 ['a', 'b'](a,b),也可以传入'a b''a,b' 这种被逗号或空格分割的单字符串。

上文中如果你希望看到类被构建的过程,可以增加参数 verbose,但是这个参数在官网也有相关的说明,有的版本是不支持的,在 Python 3.7 之后就没有该属性了。

代码语言:txt
复制
Changed in version 3.6: The verbose and rename parameters became keyword-only arguments.
Changed in version 3.6: Added the module parameter.
Changed in version 3.7: Removed the verbose parameter and the _source attribute.
Changed in version 3.7: Added the defaults parameter and the _field_defaults attribute.

初始化空列表是使用 list() 还是使用 []

该内容可以使用下述代码进行一下效率的测试。

代码语言:txt
复制
import timeit
a = timeit.timeit('a=list()', number=10000000 )
b = timeit.timeit('a=[]', number=10000000 )
print(a)
print(b)

运行结果:

代码语言:txt
复制
1.6634819
0.5888171999999998

结论是 [] 速度更快,因为 list() 是函数调用,效率肯定要低一些。

有了上述函数,你也可以测试一下相同的元素在列表与元组初始化的时候,哪个效率更好。

代码语言:txt
复制
import timeit
a = timeit.timeit('a=("a","b","c")', number=10000)
b = timeit.timeit('b=["a","b","c"]', number=10000)
print(a)
print(b)

运行结果如下:

代码语言:txt
复制
# 初始化元组
0.0005571000000000048
# 初始化列表
0.002022099999999999

1.5 这篇博客的总结

这篇博客,重点回顾了列表与元组的一些基础内容,并且探究了一下列表与元组在系统分配上的差异,额外为大家扩展了一个 namedtuple 函数,最后你可以扩展了解一下 timeit 模块。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、列表与元组那些事儿
    • 1. 列表和元组为何要总放在一起
      • 1.1 列表和元组的切片
        • 1.2 负数索引与二者相互转换
          • 1.3 列表与元组的存储方式
            • 1.4 列表和元组的应用场景
            • 1.5 这篇博客的总结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档