我心中的王者:Python-第8章 元组(Tuple)
在大型的商业或游戏网站设计中,列表(list)是非常重要的数据类型,因为记录各种等级客户、游戏角色等,皆需要使用列表,列表数据可以随时变动更新。Python提供另一种数据类型称元组(tuple),这种数据类型结构与列表完全相同,但是它与列表最大的差异是,它的元素值与元素个数不可更改,有时又可称不可改变的列表,这也是本章的主题。
8-1 元组的定义
列表在定义时是将元素放在中括号内,元组的定义则是将元素放在小括号“( )”内,下列是元组的语法格式。
name_tuple = (元素1, … , 元素n) # name_tuple是假设的元组名称
基本上元组的每一个数据称元素,元素可以是整数、字符串或列表等,这些元素放在小括号( )内,彼此用逗号“,”隔开。如果要打印元组内容,可以用print( )函数,将元组名称当作变量名称即可。
如果元组内的元素只有一个,在定义时需在元素右边加上逗号“,”。
name_tuple = (元素1,) # 只有一个元素的元组
程序实例ch8_1.py:定义与打印元组,最后使用type( )列出元组数据类型。
# ch8_1.py
numbers1 = (1, 2, 3, 4, 5) # 定义元组元素是整数
fruits = ('apple', 'orange') # 定义元组元素是字符串
mixed = ('James', 50) # 定义元组元素是不同型态数据
val_tuple = (10,) # 只有一个元素的元祖
print(numbers1)
print(fruits)
print(mixed)
print(val_tuple)
# 列出元组数据型态
print("元组mixed数据型态是: ",type(mixed))
执行结果
(1, 2, 3, 4, 5)
('apple', 'orange')
('James', 50)
(10,)
8-2 读取元组元素
定义元组时是使用小括号“( )”,如果想要读取元组内容,和列表是一样的,用中括号“[ ]”。在Python中元组元素是从索引值0开始配置。所以如果是元组的第一个元素,索引值是0,第二个元素索引值是1,其他依次类推,如下所示:
程序实例ch8_2.py:读取元组元素的应用。
name_tuple[i] # 读取索引i的元组元素
# ch8_2.py
numbers1 = (1, 2, 3, 4, 5) # 定义元组元素是整数
fruits = ('apple', 'orange') # 定义元组元素是字符串
val_tuple = (10,) # 只有一个元素的元祖
print(numbers1[0]) # 以中括号索引值读取元素内容
print(numbers1[4])
print(fruits[0])
print(fruits[1])
print(val_tuple[0])
执行结果
1
5
apple
orange
10
8-3 遍历所有元组元素
在Python可以使用for循环遍历所有元组元素。
程序实例ch8_3.py:假设元组是由字符串和数值组成的密码,这个程序会列出元组所有元素内容。
# ch8_3.py
keys = ('magic', 'xaab', 9099) # 定义元组元素是字符串与数字
for key in keys:
print(key)
执行结果
magic
xaab
9099
8-4 修改元组内容产生错误的实例
本章前言笔者已经说明元组元素内容是不可更改的,下列是尝试更改元组元素内容的错误实例。
程序实例ch8_4.py:修改元组内容产生错误的实例。
# ch8_4.py
fruits = ('apple', 'orange') # 定义元组元素是字符串
print(fruits[0]) # 打印元组fruits[0]
fruits[0] = 'watermelon' # 将元素内容改为watermelon
print(fruits[0]) # 打印元组fruits[0]
执行结果 下列是列出错误的画面。
apple
Traceback (most recent call last):
File "e:\桌面Desktop\Python王者归来\代码\ch8\ch8_4.py", line 4, in <module>
fruits[0] = 'watermelon' # 将元素内容改为watermelon
~~~~~~^^^
TypeError: 'tuple' object does not support item assignment
上述最后一行错误信息TypeError指出tuple对象不支持赋值,相当于不可更改它的元素值。
8-5 可以使用全新定义方式修改元组元素
如果我们想修改元组元素,可以使用重新定义元组方式处理。
程序实例ch8_5.py:用重新定义方式修改元组元素内容。
# ch8_5.py
fruits = ('apple', 'orange') # 定义元组元素是水果
print("原始fruits元组元素")
for fruit in fruits:
print(fruit)
fruits = ('watermelon', 'grape') # 定义新的元组元素
print("\n新的fruits元组元素")
for fruit in fruits:
print(fruit)
执行结果
原始fruits元组元素
apple
orange
新的fruits元组元素
watermelon
grape
8-6 元组切片(tuple slices)
元组切片观念与6-1-3节列表切片观念相同,下列将直接用程序实例说明。
程序实例ch8_6.py:元组切片的应用。
# ch8_6.py
fruits = ('apple', 'orange', 'banana', 'watermelon', 'grape')
print(fruits[1:3])
print(fruits[:2])
print(fruits[1:])
print(fruits[-2:])
print(fruits[0:5:2])
执行结果
('orange', 'banana')
('apple', 'orange')
('orange', 'banana', 'watermelon', 'grape')
('watermelon', 'grape')
('apple', 'banana', 'grape')
8-7 方法与函数
应用在列表上的方法或函数如果不会更改元组内容,则可以将它应用在元组,如len( )。如果会更改元组内容,则不可以将它应用在元组,如append( )、insert( )或pop( )。
程序实例ch8_7.py:列出元组元素长度(个数)。
# ch8_7.py
keys = ('magic', 'xaab', 9099) # 定义元组元素是字符串与数字
print("keys元组长度是 %d " % len(keys))
执行结果
keys元组长度是 3
程序实例ch8_8.py:误用会减少元组元素的方法pop( ),产生错误的实例。
# ch8_8.py
keys = ('magic', 'xaab', 9099) # 定义元组元素是字符串与数字
key = keys.pop( ) # 错误
执行结果
Traceback (most recent call last):
File "e:\桌面Desktop\Python王者归来\代码\ch8\ch8_8.py", line 3, in <module>
key = keys.pop( ) # 错误
^^^^^^^^
AttributeError: 'tuple' object has no attribute 'pop'
上述指出错误是不支持pop( ),这是因为pop( )将造成元组元素减少。
程序实例ch8_9.py:误用会增加元组元素的方法append( ),产生错误的实例。
# ch8_9.py
keys = ('magic', 'xaab', 9099) # 定义元组元素是字符串与数字
keys.append('secret') # 错误
执行结果
Traceback (most recent call last):
File "e:\桌面Desktop\Python王者归来\代码\ch8\ch8_9.py", line 3, in <module>
keys.append('secret') # 错误
^^^^^^^^^^^
AttributeError: 'tuple' object has no attribute 'append'
8-8 列表与元组数据互换
程序设计过程,也许会有需要将列表(list)与元组(tuple)数据类型互换,可以使用下列指令。
list( ):将元组数据类型改为列表。
tuple( ):将列表数据类型改为元组。
程序实例ch8_10.py:重新设计ch8_8.py,将元组改为列表的测试。
# ch8_10.py
keys = ('magic', 'xaab', 9099) # 定义元组元素是字符串与数字
list_keys = list(keys) # 将元组改为列表
list_keys.append('secret') # 增加元素
print("打印元组", keys)
print("打印列表", list_keys)
执行结果
打印元组 ('magic', 'xaab', 9099)
打印列表 ['magic', 'xaab', 9099, 'secret']
上述第4行由于list_keys已经是列表,所以可以使用append( )方法。
程序实例ch8_11.py:将列表改为元组的测试。
# ch8_11.py
keys = ['magic', 'xaab', 9099] # 定义列表元素是字符串与数字
tuple_keys = tuple(keys) # 将列表改为元组
print("打印列表", keys)
print("打印元组", tuple_keys)
tuple_keys.append('secret') # 增加元素 --- 错误错误
执行结果
打印列表 ['magic', 'xaab', 9099]
打印元组 ('magic', 'xaab', 9099)
Traceback (most recent call last):
File "e:\桌面Desktop\Python王者归来\代码\ch8\ch8_11.py", line 6, in <module>
tuple_keys.append('secret') # 增加元素 --- 错误错误
^^^^^^^^^^^^^^^^^
AttributeError: 'tuple' object has no attribute 'append'
上述前5行程序是正确的,所以可以看到有分别打印列表和元组元素,程序第6行的错误是因为tuple_keys是元组,不支持使用append( )增加元素。
8-9 其他常用的元组方法
程序实例ch8_12.py:元组内建方法max( )、min( )的应用。
# ch8_12.py
tup = (1, 3, 5, 7, 9)
print("tup最大值是", max(tup))
print("tup最小值是", min(tup))
执行结果
tup最大值是 9
tup最小值是 1
8-10 enumerate对象使用在元组
在6-11与7-5节皆已有说明,在此笔者直接以实例解说。
程序实例8_13.py:将元组转成enumerate对象,再转回元组对象。
# ch8_13.py
drinks = ("coffee", "tea", "wine")
enumerate_drinks = enumerate(drinks) # 数值初始是0
print("转成元组输出, 初始值是 0 = ", tuple(enumerate_drinks))
enumerate_drinks = enumerate(drinks, start = 10) # 数值初始是10
print("转成元组输出, 初始值是10 = ", tuple(enumerate_drinks))
执行结果
转成元组输出, 初始值是 0 = ((0, 'coffee'), (1, 'tea'), (2, 'wine'))
转成元组输出, 初始值是10 = ((10, 'coffee'), (11, 'tea'), (12, 'wine'))
程序实例ch8_14.py:将元组转成enumerate对象,再解析这个enumerate对象。这个程序基本上只是修改ch7_37.py,将列表改为元组。
# ch8_14.py
drinks = ("coffee", "tea", "wine")
# 解析enumerate物件
for drink in enumerate(drinks): # 数值初始是0
print(drink)
for count, drink in enumerate(drinks):
print(count, drink)
print("****************")
# 解析enumerate物件
for drink in enumerate(drinks, 10): # 数值初始是10
print(drink)
for count, drink in enumerate(drinks, 10):
print(count, drink)
执行结果 与ch7_37.py相同。
8-11 zip( )
这是一个内置函数,参数内容主要是可迭代(iterable)的对象,如列表等。然后将相对应的元素打包成元组(tuple),最后传给zip对象,我们可以使用list( )函数将zip对象转成列表。
程序实例ch8_15.py:zip( )的应用。
# ch8_15.py
fields = ['Name', 'Age', 'Hometown']
info = ['Peter', '30', 'Chicago']
zipData = zip(fields, info) # 执行zip
print(type(zipData)) # 打印zip数据类型
player = list(zipData) # 将zip数据转成列表
print(player) # 打印列表
执行结果
<class 'zip'>
[('Name', 'Peter'), ('Age', '30'), ('Hometown', 'Chicago')]
如果放在zip( )函数的列表参数长度不相等,由于多出的元素无法匹配,转成列表对象后zip对象元素数量将是较短的数量。
程序实例ch8_16.py:重新设计ch8_15.py,fields列表元素数量个数是3个,info列表元素数量个数只有2个,最后zip对象元素数量是2个。
# ch8_16.py
fields = ['Name', 'Age', 'Hometown']
info = ['Peter', '30']
zipData = zip(fields, info) # 执行zip
print(type(zipData)) # 打印zip数据类型
player = list(zipData) # 将zip数据转成列表
print(player) # 打印列表
执行结果
<class 'zip'>
[('Name', 'Peter'), ('Age', '30')]
如果在zip( )函数内增加“*”符号,相当于可以unzip( )列表。
程序实例ch8_17.py:扩充设计ch8_15.py,恢复zip前的列表。
# ch8_17.py
fields = ['Name', 'Age', 'Hometown']
info = ['Peter', '30', 'Chicago']
zipData = zip(fields, info) # 执行zip
print(type(zipData)) # 打印zip数据类型
player = list(zipData) # 将zip数据转成列表
print(player) # 打印列表
f, i = zip(*player) # 执行unzip
print("fields = ", f)
print("info = ", i)
执行结果
<class 'zip'>
[('Name', 'Peter'), ('Age', '30'), ('Hometown', 'Chicago')]
fields = ('Name', 'Age', 'Hometown')
info = ('Peter', '30', 'Chicago')
8-12 元组的功能
读者也许好奇,元组的数据结构与列表相同,但是元组有不可更改元素内容的限制,为何Python要有类似但功能却受限的数据结构存在?原因是元组有下列优点。
- 可以更安全地保护数据
程序设计中可能会碰上有些数据是永远不会改变的情况,将它存储在元组(tuple)内,可以安全地被保护。例如,电子邮件的数据结构,图像处理时对象的长、宽或每一像素的色彩数据,很多都是以元组为数据类型。
- 增加程序执行速度
元组(tuple)结构比列表(list)简单,占用较少的系统资源,程序执行时速度比较快。
当了解了上述元组的优点后,其实未来设计程序时,如果确定数据可以不更改,就尽量使用元组数据类型吧!