主要参考的是Github上的一个项目:https://github.com/jackfrued/Python-100-Days 文章主要是对该项目中的内容进行学习 穿插一点自己的学习想法等内容~
嵌套列表
names = ['关羽', '张飞', '赵云', '马超', '黄忠']
courses = ['语文', '数学', '英语']
# 录入五个学生三门课程的成绩
# 错误 - 参考http://pythontutor.com/visualize.html#mode=edit
# scores = [[None] * len(courses)] * len(names)
scores = [[None] * len(courses) for _ in range(len(names))]
for row, name in enumerate(names):
for col, course in enumerate(courses):
scores[row][col] = float(input(f'请输入{name}的{course}成绩: '))
print(scores)
该代码的目的是为了构造一个names做行 courses做列的表格来记录五个人的三门功课成绩。
实际上即为构造一个5 × 3的二维数组。直接用循环造一个空的往里边填数字也不是不行-_-
列表嵌套存在的意义就是简化用循环去构造一个空列表的繁琐代码。
错误代码
首先来看一下文中写的那段错误的代码~
scores = [[None] * len(courses)] * len(names)
自我分析
首先是一个空列表重复 len(courses) 次构成一个新列表,结果就是[[], [], []]
上述生成的列表再重复 len(names) 次,结果就是[[], [], []], [[], [], []], [[], [], []], [[], [], []], [[], [], []]?
是不是这个样子哇.....
结果运行
只运行这三行代码,结果显示scores的内容如下:
[[None, None, None], [[None, None, None], [[None, None, None], [[None, None, None], [[None, None, None]]
None
且来科普一下None
None是一个特殊的常量,N必须大写。它不表示0,不表示空字符串,表示没有值(空值),数据类型是NoneType
空值与空对象不同,空值和占位符感觉差不多,知道这里应该有东西 但具体是什么不知道。空对象就是只定义了类型,里边什么都不知道,有几个等信息都不知道。
常用于assert、判断以及函数无返回值的情况。例如使用print函数输出数据,函数的返回值就是None。在不得不设置返回值的地方起到了一个占位作用。
Python函数中不写返回值,默认返回None;最后只写了return 同理。
揭秘
将分析语句变成两个语句去执行
a = [[None] * len(courses)]
b = a * * len(names)
你会发现更改会对a和b同时生效,建立索引的时候你的列表行索引并没有太大用处。操作就是找到列 然后修改那一列的所有元素。
实际上就是修改了列表a 然后重复列表a 表现在b中
所以这样的嵌套是失败的,最后你只能得到所有人的分数都和黄忠一样。
猜测应该是先构造了一个1 * 3 的列表,然后重复了5次,最后外边加了一个框 像二维数组一样【实际上并不是】
从下边的这张图中就可以明显地看出来原因!证明我们的推测!
正确代码
scores = [[None] * len(courses) for _ in range(len(names))]
自我分析
一看外边的框就知道这是一个列表嵌套,外边是一个数组,里边是一个数组。
这样采用for循环去重复 就解除了列表之间的联系,每个都不一样,所以可以单独编辑不受影响。
总结反思
http://pythontutor.com/visualize.html#mode=display
上述这个链接可以看到代码执行时内存空间及值的分配情况,直观看出来错误原因出现在哪里!
使用列表嵌套时可以先写个简单的小例子测试一下
【当然还是知道原理最重要】
参考链接
http://c.biancheng.net/view/5659.html