文章目录
- 1.元组的概念
- 2.元组的基本使用
- 2.1.定义一个元组
- 2.2.定义一个空元组
- 2.3.元组的元素是不可变的
- 2.4.当元组中的元素是一个列表时列表中的元素可变
- 2.5.当元组中只定义一个元素时的注意事项
- 3.列表的所有操作同样适用于元组
- 4.就是想修改元组中的某个元素
1.元组的概念
Python中的元组和列表很相似,元组也是Python语言提供的内置数据结构之一,可以在代码中直接使用。
元组和列表就像是一个孪生兄弟,表现形式和使用上都大差不差,但是两者又有非常明显的区别:
- 元组是用小括号表示的,列表的小括号还可以直接省略,而列表是使用中括号表示的,列表的中括号必须存在。
- 元组的对象是不可变类型的,也就是说,一旦定义了元组,元组中的数据时不能进行更改的。
- 列表中的对象是可变类型的,定义了列表之后,可以对列表中的数据进行增删改。
一个元组中也会定义很多个数据元素,每个数据元素也都可以通过索引的方式获取,也有正数、负数索引一说。
当一个元组中的数据元素是一个列表时,对于元素是不允许修改的,但是元素中列表的数据时可以被修改的,有种多维列表的概念,这个列表在元组中相当于一个子列表,这种情况在下面的操作中会进行演示。
问题来了,既然元组和列表那么的相似,为什么还要设计元组这种数据结构呢?
其实也并不难理解,元组的对象是不可变类型的,一旦创建了元组这种不可变类型的对象,对象中的所有数据将不能修改,也能够避免由于修改数据从而引发的Bug错误,此外,对于不可变类型的对象值,在多并发的环境下是不需要加锁的,因为它的数据不可能会被改变,因此多并发的时候就不需要加锁,从而避免并发1修改了数据并发2依旧是旧数据。
因此在程序中我们也要尽量使用不可变类型的对象。
当元组中存在一个列表对象时,为什么列表中的元素可以被修改?不是说元组的对象是不可变类型吗?
因为一个元组中有很多个元素,列表呢只属于其中的一个元素,对应一个索引,对于元组而言存储的是引用元素所在内存中的地址,存储引用的内存地址是不会被改变的,也就意味着元组中的元素定义好之后,不能再添加、删除元组中的对象元素,但是列表只是元组中的一个元素,即使修改列表的数据也不会对元组中的对象元素有改动,根据列表的特点以及列表有自己的数据结构,就可以对元组中元素为列表的对象进行修改。
2.元组的基本使用
在前面说了那么多的理论,例如元组用小括号表示,元组的特性等等,在本小结,我们通过案例来是验证。
2.1.定义一个元组
元组用小括号定义。
#定义一个元组
mytuple = ("jiangxl", 123, "python")
print(mytuple)
#输出结果:('jiangxl', 123, 'python')
定义元组时小括号可以省略。
mytuple = "jiangxl", 123, "python"
print(mytuple)
#输出结果:('jiangxl', 123, 'python')
2.2.定义一个空元组
可以使用()表示一个空元组,也可以使用tuple()函数定义一个空元组
mytuple = ()
print(mytuple)
print(tuple())
2.3.元组的元素是不可变的
元组中的对象元素是不可变的,已定义好的元组,其中的元素是不能被修改的,如下所示:
mytuple = ("jiangxl", 123, "python")
#尝试修改索引为1的元素
mytuple[1] = 678
直接回抛出错误:TypeError: ‘tuple’ object does not support item assignment
2.4.当元组中的元素是一个列表时列表中的元素可变
当一个元组中的元素是一个列表时,这个列表相当于元组的一个元素,面向一个索引,此时这个列表相当于多维列表中子列表的概念,有自己的索引分布,因此当元组中的元素是列表时,这个列表中的元素可以改变。
元组会存储元素在内存中的地址,这个地址是不能被修改的,因此可以保证元素在元组中不会改变,但是列表是元组中的一个元素,这个元素对象不变就可以,至于元素中的元素就受列表的特性控制了。
#定义一个元组,其中索引1对应的元素是[1, 2, 3]列表
mytuple2 = ("jiangxl", [1, 2, 3], "python")
#修改[1, 2, 3]列表中1元素为123
'''
首先找到[1, 2, 3]列表所在元组中的元素对应的索引:mytuple2[1]
然后在找到元素1对应在列表中的索引:mytuple2[1][0]
'''
mytuple2[1][0] = 123
#打印元组的内容观察是否被修改
print(mytuple2)
#输出结果:('jiangxl', [123, 2, 3], 'python')
2.5.当元组中只定义一个元素时的注意事项
当在元素中只定义一个元素时,有一些注意事项,即使是只定义一个元素,也要在元组中至少包含一个逗号,否则Python就认为我们定义的并非是元组,只是一个字符串。
1)定义元组中只有一个元素且不加逗号
当定义的元组中只有一个元素时,并且没有加逗号,此时Python认为这并不是一个元组,只是一个字符串,()括号也被认为是数学中的括号。
#元组中只有一个元素,且不添加逗号
mytuple = ("jiangxl")
#打印这个元组中的元素
print(mytuple)
#输出结果:jiangxl
#竟然只输出了一个字符串,并不是元组的形式,我们打印这个数据的类型
print(type(mytuple))
#输出结果:<class 'str'>
#发现只是一个字符串类型,并不是元组
2)定义元组中只有一个元素且加逗号
在元组()中只要有一个逗号,Python就认为这是一个元组。
mytuple = ("jiangxl",)
3.列表的所有操作同样适用于元组
元组和列表很类似,几乎一样,只不过元组是不可变的类型,列表能实现的操作,也同样适用于元组。
理论就不再叙说了,不明白的去看前面列表这类操作的理论,说的非常明白了。
1)元组的切片
#元组的切片
mytuple = ("jiangxl", 123, "python", 111, 22, 45, "abc")
print(mytuple[1:4])
#输出结果; (123, 'python', 111)
2)查询元组中某个元素的索引
#查询元组中某个元素的索引
mytuple = ("jiangxl", 123, "python", 111, 22, 45, "abc")
print(mytuple.index(123))
#输出结果;1
3)使用乘法运算符操作列表
#使用乘法运算符操作列表
mytuple = ("jiangxl", 123, "python", 111, 22, 45, "abc")
mytuple2 = mytuple * 2
print(mytuple2)
#输出结果:('jiangxl', 123, 'python', 111, 22, 45, 'abc', 'jiangxl', 123, 'python', 111, 22, 45, 'abc')
4)使用加法运算符操作列表
#使用加法运算符操作列表
mytuple3 = ("abc", "k8s", "jenkins")
mytuple4 = (123, 456, 789, 111)
print(mytuple3 + mytuple4)
#输出结果:('abc', 'k8s', 'jenkins', 123, 456, 789, 111)
5)元组之间的比较
元组的比较也是基于元组中的所有元素都是数字的情况下,才能进行比较。
#元组的比较
mytuple5 = (1, 2, 3, 4)
mytuple6 = (1, 2, 5, 8, 9)
print(mytuple5 < mytuple6)
#输出结果:True
6)元组的反转
元组是不可变的类型,不能通过方法reverse实现元组的反转,因为调用类方法会修改元组本身的元素,所以只能通过reversed函数实现反转。
mytuple = ("jiangxl", 123, "python", 111, 22, 45, "abc")
print(list(reversed(mytuple)))
#输出结果:['abc', 45, 22, 111, 'python', 123, 'jiangxl']
7)元组的排序
元组是不可变的类型,不能通过方法sort实现元组排序,因为调用类方法会修改元组本身的元素,所以只能通过sorted函数实现排序。
元组进行排序时,如果元组中存在字符串类型的元素,那么其他所有的元素无论什么类型,都需要单独用引号引起来,否则不能排序,会抛出错误。
mytuple = (1, 2, 5, 8, 9)
##升序
print(sorted(mytuple))
#输出结果:[1, 2, 5, 8, 9]
##降序
print(sorted(mytuple, reverse=True))
#输出结果:[9, 8, 5, 2, 1]
4.就是想修改元组中的某个元素
元组的对象是不可变类型的,不允许增、删、改,但是我们就是想改元组的对象元素,也是有办法的。
- 重新声明元组,对元素进行增删改
- 使用切片截取元组中需要的元素,然后是还有加法运算符拼接新的对象元素。
第一种方法无需演示,懂得都会,重点看第二种方法。
这种方法的核心思想就是:利用切片(保留元组中想要的元素)+拼接(将多个切片的元组合并)的方式即可对元组中的元素改变。
需求:
(“jiangxl”, 123, “python”, 111, 22, 45, “abc”)
有一个元组,对象元素如上所示,我想删掉元组中的“22”和“45”这两个对象元素。
实现思路:
- 我们都知道元组是不可变的类型,不允许修改其中的元素,但是我们就要反其道而行之,运用所学的知识实现这个需求。
- 想删掉元组中的“22”和“45”这两个对象元素,可以使用切片的方式将这两个元素之外的元素从列表中切出来。
- 由于这两个元素前后都有其他元素,一个切片截取22元素之前的其他元素,一个切片截取45元素之后的其他元素。
- 最后通过加法运算符将两个切片合并在一起,形成一个新的元组,此时这个元组中就不包含22”和“45”这两个对象元素。
- 通过切片+拼接的方法就可以将元组中的元素进行删除操作,如果是修改也是同样的方法:切片+拼接。
代码如下:
#定义初始元组
'''
定义好初始元组后,突然想修改元组中的元素了,但是又不想去调整初始元组,故而通过切片+拼接的方法产生一个新的元组,也就相当于对元组的元素进行改变了。
需求:删掉元组中的“22”和“45”这两个对象元素
'''
mytuple = ("jiangxl", 123, "python", 111, 22, 45, "abc")
'''
使用切片截取22元素之前的其他元素,无需指定起始索引,从第一个元素处开始截取,指定结束索引为4
索引4是元素22的索引,指定结束元素是4,结束元素不会被纳入切片
'''
mytuplestart = mytuple[:4]
'''
22元素之前的全部元素都截取出来后,还要对45之后的元素进行截取,因为我们只是不想要22和45了,45之后还有其他的元素
指定开始索引为6,索引为6的元素是abc,完美避开了22和45这两个元素,不指定结束索引,一直切片到最后一个元素
'''
mytuolestop = mytuple[6:]
'''
使用加法运算符将两个切片拼接在一起,形成新的元组
'''
mytuplenew = mytuplestart + mytuolestop
print(mytuplenew)
#输出结果:('jiangxl', 123, 'python', 111, 'abc')