B站|公众号:啥都会一点的研究生
hello,我是啥都生,本期将Python中元组涉及的从基础到进阶用法,全部总结归纳,最后还会与列表进行对比,一起看看吧~
首先是元组的创建,空元组可以通过如下两种方式定义
tuple1 = ()
tuple2 = tuple()
print(tuple1, tuple2)
>>> () ()
小括号内输入元素完成非空元组的创建,由逗号隔开相邻元素,元素内容可重复,类型可不同
tuple1 = (1, 1, 2, 2)
tuple2 = (1, "q", True)
print(tuple1, tuple2)
>>> (1, 1, 2, 2) (1, 'q', True)
值得一提的是,如果定义一个新对象如下,打印其类型会发现是元组
data1 = 1,
data2 = 1, "q", True
print(type(data1), type(data2))
>>> <class 'tuple'> <class 'tuple'>
此外,若在小括号内添加一个字符串对象如下,打印会发现其类型是仍为字符串
data1 = ("q")
print(type(data1))
>>> <class 'str'>
正确的语法应该是在其后添加一个逗号,再次打印,类型为元组
data1 = ("q",)
print(type(data1))
>>> <class 'tuple'>
此外,可以使用内置函数将可迭代列表转为元组
data1 = tuple([1, "a", True])
print(type(data1))
>>> <class 'tuple'>
关于索引取值,与列表相同,使用正数表示从左至右取元素值,从0开始表示最左边元素,以此类推,即最右边元素为列表长度减一
tuple1 = (1, 2, 3, 4, 5)
first = tuple1[0]
last = tuple1[5-1]
print(first, last)
>>> 1 5
同样可以使用负数表示从右至左取值,但注意此时从**-1开始表示最右边元素**
tuple1 = (1, 2, 3, 4, 5)
first = tuple1[-1]
last = tuple1[-5]
print(first, last)
>>> 5 1
如果索引超出范围[0, length(list)-1],则会抛出IndexError
tuple1 = (1, 2, 3, 4, 5)
data = tuple1[5]
>>> Traceback (most recent call last):
File "script.py", line 5, in <module>
data = tuple1[5]
IndexError: tuple index out of range
Exited with error status 1
搭配冒号:
可以实现更多索引切片玩法,取列表中某一段元素值使用如下方式,注意左闭右开,seg1表示取从左至右第一个元素至第三个元素,seg2表示取从左至右第三个元素至第五个元素
tuple1 = (1, 2, 3, 4, 5)
seg1 = tuple1[0:3] # 通常写成list1[:3] 适用于从初始位置开始的切片
seg2 = tuple1[2:5] # 通常写成list1[2:] 适用于以末尾位置结束的切片
print(seg1, seg2)
>>> (1, 2, 3) (3, 4, 5)
同样的适用于负数,但通常不这么做,也不建议这样
tuple1 = (1, 2, 3, 4, 5)
seg1 = tuple1[-3:-1]
print(seg1)
>>> (3, 4)
使用双冒号::
实现隔值索引,该例表示从索引位置1开始每两个位置取值
tuple1 = tuple(range(20))
seg1 = tuple1[1::2]
print(seg1)
>>> (1, 3, 5, 7, 9, 11, 13, 15, 17, 19)
同样适用于负数,值得一提的是,双冒号::
搭配-1
起到翻转的作用
tuple1 = tuple(range(20))
seg1 = tuple1[::-1]
print(seg1)
>>> (19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
需要特别注意的是,列表是不可变对象,所以无法改变元素值,单个赋值、某片段赋值均不支持
tuple1 = (1, 2, 3, 4, 5, 6)
tuple1[0] = 10 # 单值更改
tuple1[2:4] = "ab" # 多值更改
>>> Traceback (most recent call last):
File "script.py", line 5, in <module>
tuple1[0] = 10 # 单值更改
TypeError: 'tuple' object does not support item assignment
Exited with error status 1
接着讲讲元组支持的方法,使用index
返回某元素在元组中的位置索引,若出现多次,则返回第一次出现的位置索引
tuple1 = (1, 2, 3, 3, 5)
idx = tuple1.index(3)
print(idx)
>>> 2
使用count
统计元组中某元素出现次数
tuple1 = (1, 4, 4, 4, 5)
num = tuple1.count(4)
print(num)
>>> 3
此外,元组支持的内置函数用法,使用min
返回元组中最小元素
tuple1 = (1, 2, 3, 4, 5)
data = min(tuple1)
print(data)
>>> 1
使用max
返回元组中最大元素
tuple1 = (1, 2, 3, 4, 5)
data = max(tuple1)
print(data)
>>> 5
使用len
返回元组长度
tuple1 = (1, 2, 3, 4, 5)
num = len(tuple1)
print(num)
>>> 5
再就是元组的解包,首先是基本的解包方式
tuple1 = 1, True, "aa"
first, second, third = tuple1
print(first, second, third)
>>> 1 True aa
如果元组元素过多,而仅需要前几位,可以这样
tuple1 = tuple(range(20))
first, second, *other = tuple1
print(first, second)
print(other)
>>> 0 1
>>> [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
还没完,还可以这样
tuple1 = tuple(range(20))
first, *other, last = tuple1
print(first, last)
print(other)
>>> 0 19
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
这样
tuple1 = tuple(range(20))
*other, penultimate, last = tuple1
print(penultimate, last)
print(other)
>>> 18 19
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
再说说元组的遍历,通常使用循环直接遍历列表
tuple1 = ("one", "two", "three")
for i in tuple1:
print(i)
>>> one
two
three
如果需要用到位置索引,更好的方式是使用enumerate
tuple1 = ("one", "two", "three")
for data in enumerate(tuple1):
print(data)
>>> (0, 'one')
(1, 'two')
(2, 'three')
才学完解包,所以可以写成如下形式
tuple1 = ("one", "two", "three")
for index, item in enumerate(tuple1):
print(index, item)
>>> 0 one
1 two
2 three
判断某元素是否存在于元组中,可以使用如下方式
tuple1 = ("one", "two", "three")
if "two" in tuple1:
print(True)
>>> True
重点来了,元组与列表有什么区别呢,我们打印对比看看二者支持的方法有哪些区别
my_list = list(range(5))
my_tuple = tuple(range(5))
print(dir(my_list))
print(dir(my_tuple))
>>> ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
可以发现,除开标准的内置方法,列表比元组拥有更多方法,‘append’, ‘clear’, ‘copy’, ‘extend’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’,这也导致了列表付出了更多代价
,你没听错,看这个例子。定义元组与列表,其中存放相同元素,借助sys
库中getsizeof
方法进行比较,打印会发现列表占用的资源更多
import sys
my_list = [i for i in range(5)]
my_tuple = (i for i in range(5))
print("List Size : ", sys.getsizeof(my_list))
print("Tuple Size : ", sys.getsizeof(my_tuple))
>>> List Size : 120
>>> Tuple Size : 112
当数据更大时,对比将更明显
import sys
my_list = [i for i in range(10000)]
my_tuple = (i for i in range(10000))
print("List Size : ", sys.getsizeof(my_list))
print("Tuple Size : ", sys.getsizeof(my_tuple))
>>> List Size : 87616
>>> Tuple Size : 112
由于列表是可变的,元组是不可变的,无法对创建好的元组进行修改。这也使得元组优化的更好,创建更迅速,看个例子,使用timeit库,分别对拥有相同元素的列表与元组进行十万次构建,对比发现元组更迅速
import timeit
list_test = timeit.timeit(stmt="[1, 2, 3, 4, 5]", number=100000)
tuple_test = timeit.timeit(stmt="(1, 2, 3, 4, 5)", number=100000)
print("List Time : ", list_test)
print("Tuple Time : ", tuple_test)
>>> List Time : 0.01921677589416504
>>> Tuple Time : 0.0007642656564712524
以上就是本期的全部内容,欢迎纠错与补充,整理不易,点赞收藏关注鼓励下吧,一起进步~