关于python:抬抬小手学Python-列表与元组那些事儿附源码

42次阅读

共计 3319 个字符,预计需要花费 9 分钟才能阅读完成。

一、列表与元组那些事儿

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

列表和元组在根底篇曾经好好的钻研了根底用法,你应该保留一个根本印象就是列表和元组,就是一个能够搁置任意数据类型的有序汇合,或者当成一个容器也能够。

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

在很多中央,会把这种区别叫做 动静 动态

这里最常见的一个谬误就是给元组赋值或者批改值了,谬误提醒如下,呈现了要晓得起因是啥?

TypeError: 'tuple' object does not support item assignment

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

# 幻想橡皮擦 专用的反爬虫正文
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 列表和元组的切片

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

my_tuple = my_old_tuple+my_new_tuple
print(my_tuple[1:3])

在刚学习切片的时候,一个比拟常见的谬误如下,该谬误产生的起因是,[] 中括号外面的 : 写成其余符号了。

TypeError: tuple indices must be integers or slices, not tuple

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

列表与切片二者都反对 正数索引 取值,然而须要晓得正数索引是从 -1 开始的,为啥?本人推敲。

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

二者也能够相互转换,转换利用的是内置的函数 listtuple,顺着函数学习上来,列表与元组都有一些能够利用的内置函数,这部分在滚雪球第一遍学习的时候,咱曾经都搞定了,很简略的知识点。

1.3 列表与元组的存储形式

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

my_list = ["a", "b", "c"]
print(my_list.__sizeof__())

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

输入的后果存在差别,雷同元素数据的列表与元组,零碎给列表调配的空间要大一些

64
48

第一个知识点是 __sizeof__(): 示意的打印零碎调配空间的大小。

接下来咱们对其进行一下根本的测试,从列表检测零碎调配是如何进行空间调配的。

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__())

运行后果为:

初始化大小 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 须要先进行导入。

from collections import namedtuple
help(namedtuple)

函数原型如下:

namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
# Returns a new subclass of tuple with named fields.

先写一段测试代码:

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 之后就没有该属性了。

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() 还是应用 []

该内容能够应用下述代码进行一下效率的测试。

import timeit
a = timeit.timeit('a=list()', number=10000000 )
b = timeit.timeit('a=[]', number=10000000 )
print(a)
print(b)

运行后果:

1.6634819
0.5888171999999998

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

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

import timeit
a = timeit.timeit('a=("a","b","c")', number=10000)
b = timeit.timeit('b=["a","b","c"]', number=10000)
print(a)
print(b)

运行后果如下:

# 初始化元组
0.0005571000000000048
# 初始化列表
0.002022099999999999

1.5 这篇博客的总结

这篇博客,重点回顾了列表与元组的一些根底内容,并且探索了一下列表与元组在零碎调配上的差别,额定为大家扩大了一个 namedtuple 函数,最初你能够扩大理解一下 timeit 模块。

正文完
 0