成员运算符 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 就是 列表 + 列表 + 列表 的简写。
元组
我们说过,列表内的元素是可以修改的,我们使用这个特征,方便地记录同学们不断变动的出勤情况。
不过有些时候,我们希望数据能安全地保存在那里,不会变动。比如上次的期中考试成绩是要长期保存的,我们虽然记录在了列表里,但要是哪天不小心手滑了,进行了“增删改”中的任何一种动作,那就不好办了。有没有什么办法,把列表“锁定”呢?
下面,我们就介绍一种和列表很相似的数据类型——元组(tuple),满足我们对数据安全的需求。
元组和列表非常相似。不同之处在于,外观上:列表是被方括号包裹起来的,而元组是被圆括号包裹起来的。本质上:列表里的元素可修改,元组里的元素是 不可以“增删改” 的。
还有一个微妙的地方要注意,就是只有一个元素的元组,在格式上与列表是不同的。仅一个元素 x 的列表写成 [x], 但仅一个元素的元组要在括号内多写个逗号:(x,)。
这是因为 Python 中,圆括号承担的语法功能太多了,可以用来表示元组,也可以用于当数学运算中的小括号。(x) 这样的写法,Python 会优先理解成数学运算的小括号,所以光秃秃的 (x) 对 Python 来说就是一个套了个小括号的数学运算表达式。我们来看看代码:
single = (1)
print(type(single))
# 输出:
single = (1,)
print(type(single))
# 输出:
修改元组内部的数据,将会报错
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
# (类型错误:元组对象不支持删除操作)
但是,由于查询与分片操作并不会改变数据,所以我们说的两种列表元素的查询方式以及分片操作,在元组中是可用的。列表运算符,元组也都支持。用 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() 函数转换回列表。
# 枚举原排名表后,再转回列表的形式
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() 处理结果相似的嵌套结构,列表中每个元素是一个元组,元组中是排名和姓名。
enumerate() 函数中有个默认参数表示起始数字,默认为 0,所以机器才会从 0 开始数。我们可以手动输入起始数字 1,让结果更符合我们的习惯。
rank_with_ID = list(enumerate(midterm_rank, 1))
编程练习
《红楼梦》是我们四大名著之一,也是我国文学史上是最巅峰之作。作者是曹雪芹先生,也是贾宝玉的原型。
我们知道,四大名著的其它三本分别是罗贯中的《三国演义》,施耐庵的《水浒传》,以及吴承恩的《西游记》。
我们用两个列表来分别储存书名和作者:
books = ['红楼梦', '三国演义', '水浒传', '西游记']
authors = ['曹雪芹', '罗贯中', '施耐庵', '吴承恩']
你可以用我们刚刚学过的知识,将书名和作者绑定起来吗?
另外,在小贝心目中,四大名著的地位排序是:《三国演义》《西游记》《红楼梦》《水浒传》,他将四本书按他心目中的顺序录进了列表 books_favorite 中。我们能用用刚刚学过的代码帮他对 books_favorite 进行操作,附上数字表示的排名吗?
要求:
1.用 zip() 函数将 books 和 authors 以“著作名,作者”的形式结合成新列表。并将结果打印在屏幕上。
2.新建 books_favorite 列表,按小贝喜爱的顺序排列四本书。
3.用 enumerate() 函数,从 1 开始,枚举 books_favorite 列表,将结果打印在屏幕上。
books = ['红楼梦', '三国演义', '水浒传', '西游记']
authors = ['曹雪芹', '罗贯中', '施耐庵', '吴承恩']
# 用 zip() 将两个列表绑定
zip(books,authors)
# 转换回列表后打印绑定结果
print(list(zip(books,authors)))
# 新建 books_favorite 列表,顺序按小贝的喜好来
books_favorite=["三国演义","西游记","红楼梦","水浒传"]
# 用 enumerate() 函数枚举结果,从 1 开始
books_favorite_count=enumerate(books_favorite,1)
# 转换回列表后打印结果
print(list(books_favorite_count))
#输出[('红楼梦', '曹雪芹'), ('三国演义', '罗贯中'), ('水浒传', '施耐庵'), ('西游记', '吴承恩')][(1, '三国演义'), (2, '西游记'), (3, '红楼梦'), (4, '水浒传')]
range() 函数
用 range() 函数实现,快速生成一个有规律的数字序列。该函数的基本格式为 range(start, stop, step),返回一个 range 对象,要用 list() 函数转换成列表。
range() 函数最多支持 3 个参数,start 参数是起始元素,stop 参数是结束元素,step 是步长,也就是计数的间隔。其中 start 和 step 是可选的,分别默认为 0 和 1,比如 list(range(3)) 可以快速生成 [0, 1, 2] 列表。