嵌套列表(二维列表)
1.创建
  • 通过每个元素的值
matrix = [[1,2,3],[4,5,6],[7,8,9]]
martix = [[1,2,3],
          [4,5,6],
          [7,8,9]]

以上两种写法是等价的,第二种写法更加直观:

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套

  • 通过循环语句创建和初始化二维列表
A = [0] * 3
 for i in range(3):
	A[i] = [0] * 3

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_02


注意:不能通使用以下语句:

B = [[0] * 3] * 3

嵌套表格treeselect展开的树被遮挡 嵌套列表_Python_03


虽然看起来结果一样,但是这种写法在根本上就是错误的。我们修改A第二行第二列的元素,同时B也修改第二行第二列的元素。B明明只想改变一个元素,但事实上却改变了每一行的元素。

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套_04


此处引入is运算符,表明Python对于不同对象的存储机制是不一样的。字符串给定了是不可变的,只需要在内存中开辟一个位置来存储就可以了;但是列表却是可变的,所以尽管两个列表内容一样,但是Python还是会开辟两个不同的位置来存储,因为他也不知道用户会在什么时候在列表中增加或者改变某个元素。

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套_05


这里表明,A的第一、二、三行都存储在不同的位置,而B的第一、二、三行储存在了相同的位置。

到这里我们就可以明白B的问题在于试图通过乘号对一个嵌套列表进行拷贝,但其实他拷贝的只是一个列表的引用。

2.访问嵌套列表
  • 通过循环
for i in martix:
	for each in i:
		print(each)

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_06


对代码稍作改动,即内层循环每完成一次进行换行。

for i in martix:
	for each in i:
		print(each,end = ' ')
	print()

嵌套表格treeselect展开的树被遮挡 嵌套列表_Python_07

  • 通过下标
    这里只是得到了以行为单位的整个列表,而非嵌套列表中的元素。
martix[0]

嵌套表格treeselect展开的树被遮挡 嵌套列表_for语句_08


为了访问列表中的元素,我们可以使用两次下标索引,第一个下标索引的是行,第二个下标索引的是列,例如索引第一行第一列:

martix[0][0]

嵌套表格treeselect展开的树被遮挡 嵌套列表_Python_09

3.列表推导式

如何将列表中的每一个元素的值都变成原来的二倍:

  • 我们可以考虑使用一个循环,利用下标索引来更新每一个元素的值。
oho = [1, 2, 3, 4, 5]
for i in range(len(oho)):
	oho[i] = oho[i] * 2

嵌套表格treeselect展开的树被遮挡 嵌套列表_for语句_10

  • 如果使用列表推导式
    很明显这种方法更简略,列表推导式的效率通常是要比循环快上一倍左右的速度。这是因为列表推导式在Python解释器里是以更快的C语言的速度来运行的。
oho = [1, 2, 3, 4, 5]
oho = [i * 2 for i in oho]

嵌套表格treeselect展开的树被遮挡 嵌套列表_for语句_11


基本语法:

[expression for target in iterable]

列表推导式的结果是一个列表,它相当于是使用一组数据来填充这个列表,所以需要用到一个for语句来配合,最后在for语句的左侧放一个表达式,经过运算最终决定存放在列表中的数据,例如:

  • 数字
x = [i for i in range(10)]

嵌套表格treeselect展开的树被遮挡 嵌套列表_for语句_12

  • 字符
y = [c * 2 for c in "FishC"]

嵌套表格treeselect展开的树被遮挡 嵌套列表_Python_13

  • 如果想要每一个字符转换成Unicode编码并保存为列表:
code = [ord(c) for c in "FishC"]

这里ord()函数是将单个字符串转换为对应的编码

嵌套表格treeselect展开的树被遮挡 嵌套列表_Python_14

  • 如何通过列表推导式将矩阵第二列的元素提取出来:
matrix = [[1,2,3],
              [4,5,6],
              [7,8,9]]
col2 = [row[1] for row in matrix]
col2

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_15

  • 如何获取矩阵主对角线上的元素
diag = [matrix[i][i] for i in range(len(matrix))]

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_16


总结:

循环是通过迭代来逐个修改列表中的元素,而列表推导式则是直接创建了一个新的列表然后再赋值给原来的这个变量名。

带着判断条件的列表推导式
s = [[0] * 3 for i in range(3)]

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_17


他会先执行for语句,再执行判断语句,最后输出最右边的值。

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套_18


嵌套表格treeselect展开的树被遮挡 嵌套列表_python_19

4.列表推导式的嵌套

语法如下

[expression for target1 in iterable1
                    for target2 in iterable2
                    ......
                    for targetN in iterableN]
  • 将二维列表降级为一维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flatten = [col for row in matrix for col in row]

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_20


将其转换为循环的实现就理解了,外层循环放在了前面,嵌套内层的循环放在了后面:

flatten = []
for row in matrix:
	for col in row:
		flatten.append(col)

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_21

  • 再来一个例子:
[x + y for x in "fishc" for y in "FISHC"]

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套_22


在数学上可以理解为笛卡尔乘积

_ = []
for x in "fishc":
	for y in "FISHC":
		_.append(x + y)

嵌套表格treeselect展开的树被遮挡 嵌套列表_python_23

5.列表推导式的终极语法:
[expression for target1 in iterable1 if condition1
             for target2 in iterable2 if condition2
                    ......
             for targetN in iterableN if conditionN]

例如,x是0~9中能被2整除的数,即为偶数;y是能被3整除的数:

[[x, y] for x in range(10) if x % 2 == 0 for y in range(10) if y % 3 ==0]

将其转换为循环:

_ = []
for x in range(10):
	if x % 2 == 0:
		for y in range(10):
			if y % 3 == 0:
				_.append([x,y])

嵌套表格treeselect展开的树被遮挡 嵌套列表_嵌套_24


注意

非常重要的一个程序设计原则:KISS:Keep in Simple & Stupid