List and Tuple Tutorial 2¶
难度: 1
时长: 45 min
成员包含 in¶
[1,2,5,7]是否包含2呢?怎么实现?文件属性 Permissions =
"rw",检查其是否可写,是否可执行?检查输入用户名是否为合法
users = ['mlh', 'foo', 'bar']
for ... in 循环¶
打印每个成员¶
最简单的情况是不需要写索引的:
a = [1,2,3,4,5,6]
for each in a:
print(each)
案例2: 将偶数位置的成员值乘 10¶
写法1: 人工维持 index 自增¶
for ... in 循环 + 人工维持 index 自增
a = [1,2,3,4,5,6]
index = 0
for each in a:
if index % 2 == 0:
a[index] = each *10
index += 1
print(a)
写法2: 经典写法 range(len)¶
此方法需要提前知道 a 的长度:
a = [1,2,3,4,5,6]
for index in range(len(a)):
if index % 2 == 0:
a[index] = each *10
print(a)
下面的 enumerate() 写法更简洁。
写法3: enumerate()¶
让临时索引不那么可见:
a = [1,2,3,4,5,6]
for index, each in enumerate(a):
if index % 2 == 0:
a[index] = each *10
好处是代码短了2行,而且是容易出错的两行。一个是初始化,另一个是 index 的自增。这两个属于固定动作,现在用 enumerate() 给自动化了。
也可以很紧凑地用下面的代码:
a[::2] = [0] * 3
zip() 用法¶
zip() 和 enumerate() 用法是类似的,不同的是将序号换成了一个列表。例如,并行打印两个列表中的名字与年龄:
name = ['Tom', 'Alice', 'Bob']
age = [30, 42, 35]
for name, age in zip(name, age):
print(name, age)
¶
列表推导式 (List Comprehension)¶
传统写法示例:
# 传统方法
squares = []
for x in range(10):
squares.append(x**2)
更简洁的列表创建方式:
# 列表推导式
squares = [x**2 for x in range(10)]
示例:将偶数位置的成员值乘 10
# 传统方法
a = [1,2,3,4,5,6]
for index, each in enumerate(a):
if index % 2 == 0:
a[index] = each * 10
简洁写法:
# 列表推导式
a = [x * 10 if i % 2 == 0 else x for i, x in enumerate(a)]
列表示推导的语法特点:
更简洁、可读性更好
性能通常优于传统循环
支持条件过滤:
[x for x in range(10) if x % 2 == 0]支持嵌套循环
[练习2]: List for-in 修改¶
题目:学生成绩处理
scores = [85, 92, 78, 96, 88, 76, 95, 89]
将不及格分数(<60)替换为60
将前3个成绩提高10%
使用enumerate()打印每个学生的序号和成绩
[答案]
列表赋值: 指向同一对象(副作用)¶
在仿真通信系统时,接收端的信号 recv_signal 引用了发送端发送的信号 send_signal,并做了一些修改处理,却意外地发现发送信号也发生了变化:
>>> send_signal = [1,2,3,4,5]
>>> recv_signal = send_signal
>>> recv_signal[2]=10 #2 修改接收信号
>>> print(send_signal)
[1, 2, 10, 4, 5]
总结哪里有问题!!! 如何解决和避免?
改法1¶
>>> send_signal = [1,2,3,4,5]
>>> recv_signal = send_signal.copy()
>>> recv_signal[2]=10 #2 修改接收信号
>>> print(send_signal)
改法2¶
>>> send_signal = [1,2,3,4,5]
>>> recv_signal = send_signal[:]
>>> recv_signal[2]=10 #2 修改接收信号
>>> print(send_signal)
以上哪个方法正确? 你还可以用 id() 探索一下这几种情况下 send_single 和 recv_signal 之间的关系
综合练习¶
[练习3]: 列表成员查找¶
已知有一个列表 a,包含了一组学生的数据(姓名,学号),要求写一个程序,完成以下功能:
能够根据姓名或学号,查询到学生的完整记录并返回。
根据姓名,或者学号排序
数据样表:
a = [('张三', 1001),
('李四', 1002),
('王五', 1003),
('陈六', 1004),
...]
=========================
Input: '王五'
Output: ('王五', 1003)
思路:把每一行的记录都找出来,看每一行的第一个字段是姓名是什么是,是不是要找的名字,如果是,则打印结果。
示例: 通过学生「姓名」查找
a = [('张三', 1001),
('李四', 1002),
('王五', 1003),
('陈六', 1004),]
for student in a:
print(student)
print(student[0], student[1])
if student[0] == '王五':
print(student)
练习: 通过修改上面的代码,完成通过学号查找
思考:如何评价查找计算量?其计算量有多大?
[练习4]: 列表条件筛选¶
题目:学生信息管理系统(结合列表推导式)
students = [
('张三', 18, 85),
('李四', 19, 92),
('王五', 20, 78),
('赵六', 18, 96)
]
使用列表推导式获取所有学生的姓名
获取年龄大于18岁的学生信息
计算平均成绩
要求: 均使用列表推导式实现,除开打印外,其他代码只能用一行。
[答案]