成员运算符 in
我们用来判断一个元素是否在一个列表中,格式为 "元素 in 列表"。这是一个布尔表达式,如果元素在列表中,结果为布尔值 True,反之为 False。
students = [ '林黛玉','薛宝钗','贾元春','妙玉', '贾惜春', '王熙凤', '秦可卿', '贾宝玉']
miaoyu_in = '妙玉' in students
print(miaoyu_in)
# 输出:True
xiangyun_in = '史湘云' in students
print(xiangyun_in)
# 输出:False
元素 in 列表 既然是一个布尔表达式,我们就可以结合 if ... else 语句实现很多功能:
if '史湘云' in students:
print('请史湘云背诵课文')
else:
print('喊其他同学背诵吧')
# 输出:喊其他同学背诵吧
列表的加法
数字之间的加法是我们最熟悉不过的运算了,列表的加法也很简单,就是用 + 号将两个列表的元素放在一起组成一个新列表。
# 列表的加法
students = ['林黛玉', '薛宝钗', '贾元春', '贾探春', '史湘云', '妙玉', '贾迎春', '贾惜春', '王熙凤', '贾琏', '贾巧姐', '李纨', '秦可卿', '贾宝玉']
parents = ['贾敬', '贾政', '王夫人', '贾赦', '邢夫人']
meeting = students + parents
# 打印 meeting 的结果,以及最终人数
print(meeting)
print('与会人数为', len(meeting), '人')
# 输出:
# ['林黛玉', '薛宝钗', '贾元春', '贾探春', '史湘云', '妙玉', '贾迎春', '贾惜春', '王熙凤', '贾琏', '贾巧姐', '李纨', '秦可卿', '贾宝玉', '贾敬', '贾政', '王夫人', '贾赦', '邢夫人']
# 与会人数为 19 人
这样我们就用加法生成了一个完整的与会名单。要注意用加法生成的列表的元素顺序,在 + 号前的列表元素排在新列表的前面,在 + 后的列表元素在新列表的后面。
列表的乘法
列表的乘法, 用 列表 * n,我们可以生成一个元素数目为原列表 n 倍的新列表。
lag_behind = ['贾探春', '秦可卿', '贾惜春', '贾琏']
# 用乘法快速生成轮班表
recite_list = lag_behind * 5
print(recite_list)
# 输出:['贾探春', '秦可卿', '贾惜春', '贾琏', '贾探春', '秦可卿', '贾惜春', '贾琏', '贾探春', '秦可卿', '贾惜春', '贾琏', '贾探春', '秦可卿', '贾惜春', '贾琏', '贾探春', '秦可卿', '贾惜春', '贾琏']
看完上面代码的运行结果,我们发现,列表的乘法的定义,和数字的乘法很像:1 * 3 实际上是 1 + 1 + 1 的简写,那么 列表 * 3 就是 列表 + 列表 + 列表 的简写啦。
元组
元组和列表非常相似。不同之处在于,外观上:列表是被方括号包裹起来的,而元组是被 圆括号 包裹起来的。本质上:列表里的元素可修改,元组里的元素是 不可以“增删改” 的。
- 还有一个微妙的地方要注意,就是只有一个元素的元组,在格式上与列表是不同的。仅一个元素 x 的列表写成 [x], 但仅一个元素的元组要在括号内多写个逗号:(x,)。
这是因为 Python 中,圆括号承担的语法功能太多了,可以用来表示元组,也可以用于当数学运算中的小括号。(x) 这样的写法,Python 会优先理解成数学运算的小括号,所以光秃秃的 (x) 对 Python 来说就是一个套了个小括号的数学运算表达式。
有了元组这种相对稳定的数据结构,我们就再也不怕手滑把数据改掉啦!
如果真的非要去改元组内部的数据,将会报错的哦:
students = ('林黛玉', '贾宝玉', '薛宝钗')
students.append('史湘云')
# 报错:AttributeError: 'tuple' object has no attribute 'append'
# (属性错误:元组对象没有 append 属性)
# 补充说明:关于“对象”“属性”,我们在后面的课程会说
students[2] = '袭人'
# 报错:TypeError: 'tuple' object does not support item assignment
#(类型错误:元组对象不支持给其中元素赋值)
del students[1]
# 报错:TypeError: 'tuple' object doesn't support item deletion
# (类型错误:元组对象不支持删除操作)
除了上述例子外,其它的用于增加、修改或删除语句和方法都不能用在元组上
但是,由于查询与分片操作并不会改变数据,所以我们说的两种列表元素的查询方式以及分片操作,在元组中是可用的。
students = ('林黛玉', '贾宝玉', '薛宝钗')
print(students[1])
# 输出:贾宝玉
print(students.index('贾宝玉'))
# 输出:1
print(students[:2])
# 输出:('林黛玉', '贾宝玉')
另外,上一节所说的列表运算符,元组也都支持。用 in 查询元素是否在元组内;用 + 将两个元组叠加生成新元组;用 * 生成元素重复循环多次的新元组。
下面,我们总结一下元组支持的操作吧:
如果真的有特殊需求,需要修改元组中的元素,可以先用 list() 函数把元组转换成列表,相当于给数据“解锁”,将元素修改完毕后,再用 tuple() 函数转换回元组,相当于“重新上锁”。
我们在下面的代码中来看看具体的操作步骤:
students = ('林黛玉', '贾宝玉', '薛宝钗')
# 用 list() 函数给数据“解锁”,生成一个相同元素的新列表
students_list = list(students)
# 在新列表中修改元素
students_list[0] = '妙玉'
# 两次给数据“上锁”
students = tuple(students_list)
print(students)
# 输出:('妙玉', '贾宝玉', '薛宝钗')
zip() 函数
zip() 函数的作用是将两个长度相同的列表合并起来,相同位置的元素会被一一组对,变成一个元组。结果返回一个组合好的打包对象,需要我们再用 list() 函数转换回列表。
midterm_rank = [
'妙玉',
'薛宝钗',
'贾元春',
'王熙凤',
'林黛玉',
'贾巧姐',
'史湘云',
'贾迎春',
'贾宝玉',
'李纨',
'贾探春',
'秦可卿',
'贾惜春',
'贾琏']
scores = [100, 92, 77, 85, 81, 90, 100, 86, 79, 93, 91, 96, 75, 84]
# 将 scores 元素从低到高排列
scores.sort()
# 倒转 scores 中的排列顺序
scores.reverse()
print(scores)
# 输出:[100, 100, 96, 93, 92, 91, 90, 86, 85, 84, 81, 79, 77, 75]
# 用 zip() 将两个列表合并
zipped = zip(midterm_rank, scores)
# 将结果转换回列表后,赋值给 zipped_rank
zipped_rank = list(zipped)
# 来看看结果
print(zipped_rank)
# 输出:[('妙玉', 100), ('薛宝钗', 100), ('贾元春', 96), ('王熙凤', 93), ('林黛玉', 92), ('贾巧姐', 91), ('史湘云', 90), ('贾迎春', 86), ('贾宝玉', 85), ('李纨', 84), ('贾探春', 81), ('秦可卿', 79), ('贾惜春', 77), ('贾琏', 75)]
enumerate() 函数
“enumerate”单词本身意思是“枚举、数数”。所以对应的函数功能,就是一个一个地将列表中的元素数出来。它返回的是一个枚举对象,也需要我们用 list() 函数转换回列表。
有了这个函数,我们就可以把原来的排名表 midterm_rank 中,每个同学的具体排名都显示出来了。
但是要注意:机器还是会从 0 开始数……
# 枚举原排名表后,再转回列表的形式
rank_with_id = list(enumerate(midterm_rank))
print(rank_with_id)
# 输出:[(0, '妙玉'), (1, '薛宝钗'), (2, '贾元春'), (3, '王熙凤'), (4, '林黛玉'), (5, '贾巧姐'), (6, '史湘云'), (7, '贾迎春'), (8, '贾宝玉'), (9, '李纨'), (10, '贾探春'), (11, '秦可卿'), (12, '贾惜春'), (13, '贾琏')]
我们看到,最后的结果是与 zip() 处理结果相似的嵌套结构,列表中每个元素是一个元组,元组中是排名和姓名。
毕竟结果是要在现实世界中使用的,从 0 开始数的排名实在不太符合我们实际使用的要求。好在 enumerate() 函数中有个默认参数表示起始数字,默认为 0,所以机器才会从 0 开始数。我们可以手动输入起始数字 1,让结果更符合我们的习惯。
# enumerate()中这次有两个参数,一个为排名列表,一个为起始数字。
rank_with_ID = list(enumerate(midterm_rank, 1))
print(rank_with_ID)
# 输出:[(1, '妙玉'), (2, '薛宝钗'), (3, '贾元春'), (4, '王熙凤'), (5, '林黛玉'), (6, '贾巧姐'), (7, '史湘云'), (8, '贾迎春'), (9, '贾宝玉'), (10, '李纨'), (11, '贾探春'), (12, '秦可卿'), (13, '贾惜春'), (14, '贾琏')]
range() 函数
range() 函数快速生成一个有规律的数字序列。该函数的基本格式为 range(start, stop, step),返回一个 range 对象,要用 list() 函数转换成列表。
range() 函数最多支持 3 个参数,start 参数是起始元素,stop 参数是结束元素,step 是步长,也就是计数的间隔。其中 start 和 step 是可选的,分别默认为 0 和 1,比如 list(range(3)) 可以快速生成 [0, 1, 2] 列表。如下:
# 起始为 1, 结束为 36502(36501向后一位),步长默认为 1
stones = list(range(1, 36502))
# 列表太长,我们不打印内容了,直接打印列表长度、第一个元素和最后一个元素。
print('共有' + str(len(stones)) + '个元素')
print('第一个元素是' + str(stones[0]))
print('最后一个元素是' + str(stones[-1]))
# 输出:
# 共有36501个元素
# 第一个元素是1
# 最后一个元素是36501