



|
4.1 元组结构 |
元组是Python中常用的一种数据结构。元组由不同的元素组成,每个元素可以存储不同类型的数据,如字符串、数字甚至元组。元组是“写保护”的,即元组创建后不能再做任何修改操作,元组通常代表一行数据,而元组中的元素代表不同的数据项。
tuple(元组)是Python内置的一种数据结构。元组由一系列元素组成,所有元素被包含在一对圆括号中。创建元组时,可以不指定元素的个数,相当于不定长的数组,但是一旦创建后就不能修改元组的长度。元组创建的格式如下所示。
tuple = (元素1, 元素2, …)
元组的初始化示例如下:
tuple = ("apple", "banana", "grape", "orange")
上面这行代码创建了一个名为tuple的元组,该元组由4个元素组成,元素之间使用逗号分隔。
如果需要定义一个空的元组,表达方式更简单。创建空的元组只需要一对空的圆括号。
tuple = ()
如果创建的元组只包含一个元素,通常会错误地忽略单元素后的逗号。Python无法区分变量tuple是元组还是表达式,Python误认为圆括号中的内容为表达式,因此tuple[0]输出的结果并非期望的值,并且其类型也不是tuple。错误的写法如下:
01 tuple = ("apple") # 定义元组
02 print(tuple[0]) # 打印第一个元素
03 print (type(tuple)) # 打印定义的tuple的类型
运行这段代码并不会提示任何错误,代码将输出字母“a”,而不是期望的“apple”。并且其类型为<class‘str’>。正确的写法如下:
01 tuple = ("apple",) # 定义元组,注意后面的逗号不可少
02 print (tuple[0]) # 打印第一个元素
03 print (type(tuple)) # 打印定义的tuple的类型
此时,将输出tuple元组中唯一的元素“apple”,并且类型为<class‘tuple’>。所以,创建一个唯一元素的元组,需要在元素的后面添加一个逗号,使Python能正确识别出元组中的元素。
注意 元组是从0开始计数的,因此tuple[0]获得的是元组tuple中第1个元素。Python中其他的数据结构也遵循这个规则。
元组中元素的值通过索引访问,索引是一对方括号中的数字,索引也称为“下标”。元组的访问格式如下。
tuple[n]
其中,tuple[n]表示访问元组的第n个元素,索引n的值可以为0、正整数或负整数。前面一节已经提到了元组的输出方法,例如:
print (tuple[1])
上面这行代码将输出字符串“banana”,print语句表示输出,tuple[1]表示访问tuple的第2个元素。
可以把元组理解为数组,使用C或Java语言编程的读者应该不会陌生,数组的下标是从0开始计数,而元组中元素的访问也符合这个规则。
元组创建后其内部元素的值不能被修改,如果修改元组中的某个元素,运行时将报错。例如:
tuple[0] = "a"
对tuple元组中第1个元素进行赋值,运行代码后错误信息如下:
TypeError: 'tuple' object does not support item assignment
可见,元组中的元素并不支持赋值操作。
注意 元组不能添加或删除任何元素。因此,元组不存在任何添加、删除元素的方法,元组也不存在任何其他方法。
元组的访问还有一些特殊的用法,这些用法对于获取元组的值非常方便,例如负数索引和分片索引。这两个特性是Python的特殊用法,C或Java语言并不支持。负数索引从元组的尾部开始计数,最尾端的元素索引表示“-1”,次尾端的元素索引表示“-2”,以此类推。图4-1演示了负数索引与元素的对应关系,tuple[-1]的值为value4,tuple[-2]的值为value3。
分片(slice)是元组的一个子集,分片是从第1个索引到第2个索引(不包含第2个索引所指向的元素)所指定的所有元素。分片索引可以为正数或负数,两个索引之间用冒号分隔。分片的格式如下所示:
tuple[m:n]
其中,m、n可以是0、正整数或负整数。
图4-2演示了分片索引与元素的对应关系,tuple[1:3]将返回(value2,value3,value4)。
图4-1 负数索引演示
图4-2 分片索引演示
下面【例4-1】这段代码将说明负数索引和分片索引的使用。
【例4-1.py】
01 tuple = ("apple", "banana", "grape", "orange") # 定义元组
02 print (tuple[-1]) # 分片,倒数第一个元素
03 print (tuple[-2]) # 分片,倒数第二个元素
04 tuple2 = tuple[1:3] # 分片,第二个元素到第三个元素(不包括第四个)
05 tuple3 = tuple[0:-2] # 分片,从第一个元素到倒数第二个元素(不包括倒数第二个)
06 tuple4 = tuple[2:-2] # 分片,从第三个元素到倒数第二个元素(不包括倒数第二个)
07 print (tuple2)
08 print (tuple3)
09 print (tuple4)
【代码说明】
·元组的索引可以用负数表示,第2、3行代码将分别输出“orange”和“grap”。
·使用分片截取后,将得到一个新的元组。第4行到第6行代码分别创建了3个元组。
·tuple2输出结果:('banana','grape')
·tuple3输出结果:('apple','banana')
·tuple4输出结果:()
元组还可以由其他元组组成。例如,二元元组可以表示为:
tuple = (('t1', 't2'), ('t3', 't4'))
tuple是一个二元元组,该元组由('t1','t2')和('t3','t4')组成。
下面【例4-2】的代码说明了元组间的包含关系以及元组中元素的访问。
【例4-2.py】
01 fruit1 = ("apple", "banana") # 定义fruit1元组
02 fruit2 = ("grape", "orange") # 定义fruit2元组
03 tuple = (fruit1, fruit2)
04 print (tuple)
05 print ("tuple[0][1] =", tuple[0][1])
06 print ("tuple[1][1] =", tuple[1][1])
07 print ("tuple[1][1] =", tuple[1][2])
【代码说明】
·第3行代码创建了一个复合元组tuple,tuple由元组fruit1和fruit2组成。元组tuple的输出结果:
(('apple', 'banana'), ('grape', 'orange'))
·tuple[0][1]表示访问tuple元组中第1个元组的第2个元素,即fruit1元组中的第2个元素,可以把tuple理解为二维数组。tuple[0][1]输出结果:
tuple[0][1] = banana
·tuple[1][1]表示访问tuple元组中第2个元组的第2个元素,即fruit2元组中的第2个元素。tuple[1][1]输出结果:
tuple[1][1] = orange
·同理,tuple[1][2]将访问fruit2元组中的第3个元素,因为此元素不存在,元组的索引访问越界。运行后将输出如下错误信息:
IndexError: tuple index out of range
tuple元组的存储结构如图4-3所示。
图4-3 tuple元组的存储结构
创建元组的过程,Python称为“打包”。相反,元组也可以执行“解包”的操作。“解包”可以将包元组中的各个元素分别赋值给多个变量。这样,避免了使用循环遍历的方法获取每个元素的值,降低了代码的复杂性,使表达方式更自然。下面这个例子说明了元组“打包”和“解包”的过程。
01 #打包
02 tuple = ("apple", "banana", "grape", "orange")
03 #解包
04 a, b, c, d = tuple
05 print (a, b, c, d)
【代码说明】
·第2行代码创建了一个tuple元组,元组的创建即“打包”的过程。
·第4行代码使用了一个赋值操作,等号的右边是tuple元组,等号的左边有4个变量,元组tuple中的4个元素分别赋值给这4个变量。
·第5行代码输出4个变量的值,输出的结果如下:
apple banana grape orange
元组的遍历是指通过循环语句依次访问元组中各元素的值。遍历元组需要用到两个函数range()和len()。range()和len()都是Python的内建函数,这些函数可直接调用,不需要import语句导入模块。内建函数是Python自动导入的函数,相当于Java中的lang包。
len()计算出tuple元组中元素的个数,range()返回一个由数字组成的列表,关于列表的概念请参考4.2节。range()的声明如下所示。
range([start,] stop[, step]) -> list of integers
【代码说明】
·range()返回一个递增或递减的数字列表,列表的元素值由3个参数决定。
·参数start表示列表开始的值,默认值为0。
·参数stop表示列表结束的值,该参数不可缺少。
·参数step表示步长,每次递增或递减的值,默认值为1。
例如,range(5)返回的列表为[0,1,2,3,4]。下面【例4-3】这段代码实现了二元元组的遍历。
【例4-3.py】
01 tuple = (("apple", "banana"),("grape", "orange"),("watermelon",),("grapefruit",))
02 for i in range(len(tuple)):
03 print ("tuple[%d] :" % i, end = ' ')
04 for j in range(len(tuple[i])):
05 print (tuple[i][j], end = ' ')
06 print()
【代码说明】
·第1行代码创建了一个由4个子元组组成的二元元组tuple。
·第2行到第6行代码遍历tuple元组,输出元组中各个元素的值。tuple元组的遍历结果:
tuple[0] : apple banana tuple[1] : grape orange tuple[2] : watermelon tuple[3] : grapefruit
此外,也可以直接使用for…in语句遍历元组,代码如下:
01 tuple = (("apple", "banana"),("grape", "orange"),("watermelon",),("grapefruit",))
02 for i in tuple: # 遍历元组tuple
03 for j in i: # 同样对子元组进行遍历
04 print(j) # 依次打印出元素
【代码说明】
·第1行同样创建了一个元组。
·第2行开始遍历元组tuple。
·第3行开始对各子元组进行遍历。
·第4行打印出元素。
遍历结果:
apple banana grape orange watermelon grapefruit