在用python写2048小项目中,学习到了矩阵(就是二维列表)转置和翻转地代码,非常方便快捷,两种操作都只需要一行代码,显示了python强大的威力,下面写出这两行代码并做一个解析:
# 矩阵转置
def transpose(matrix):
return [list(row) for row in zip(*matrix)]
#矩阵水平翻转
def invert(matrix):
return [row[::-1] for row in matrix]
首先,matrix是一个二维列表,类似于:
matrix = [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]
- 在
t
r
a
n
s
p
o
s
e
(
)
transpose()
transpose()函数中,
∗
m
a
t
r
i
x
*matrix
∗matrix是解包操作,可以解包任何可迭代对象,而
z
i
p
zip
zip函数是压包操作。这里本质上就是
m
a
t
r
i
x
matrix
matrix被解包成三个一维的列表被传入
z
i
p
zip
zip函数中,然后
z
i
p
zip
zip函数将对应的元素进行压包,就是取第一个列表的第一个元素,第二个列表的第一个元素,第三个列表的第一个元素,构成一个元组,然后又取第一个列表的第二个元素,第二个列表的第二个元素,第三个列表的第二个元素,又构成一个元组…最终形成元组的数量取决于元素最少的那个列表。
l
i
s
t
(
r
o
w
)
list(row)
list(row)是将
z
i
p
zip
zip函数返回的可迭代对象中的元素
r
o
w
row
row这个元组给转换成列表。总结起来就是:
m a t r i x matrix matrix先被解包成三个列表,传入zip函数,zip函数将三个列表的对应元素构造成元组,然后这些元组被list转换成列表,利用 [ f o r i n ] [\quad for \quad in] [forin]这个叫列表生成式的东西将这些列表合成构造为一个列表。 - 在
i
n
v
e
r
t
invert
invert函数中,主要就是用了
r
o
w
[
:
:
−
1
]
row[::-1]
row[::−1]这个叫列表切片的东西,我研究了一下这个表达式,得出了以下结论:
对于列表切片 r [ i : j : s ] r[i:j:s] r[i:j:s], i i i是起始位置, j j j是结束位置, s s s是切片步长:- 切片步长不能为0,否则会报错。
- 切片从 r [ i ] r[i] r[i]开始,到 r [ j − 1 ] r[j-1] r[j−1]结束
- s > 0 s>0 s>0时, i i i默认为0, j j j默认为 l e n ( r ) len(r) len(r),就是r的元素个数,s不写的话默认为1,举几个例子: r [ : ] r[:] r[:]表示r的所有元素的切片, r [ 0 : l e n ( r ) ] 和 r [ : ] r[0:len(r)]和r[:] r[0:len(r)]和r[:]是相等的。
- s < 0 s<0 s<0时, i i i默认为 l e n ( r ) − 1 len(r)-1 len(r)−1, j j j默认为 1 1 1,就是从最大的开始位置,到第一个元素处结束,举几个例子: r [ : : − 1 ] r[::-1] r[::−1]就表示列表的反转, r = [ 0 , 1 , 2 , 3 ] r=[0,1,2,3] r=[0,1,2,3], r [ : : − 1 ] r[::-1] r[::−1]就是 [ 3 , 2 , 1 , 0 ] [3,2,1,0] [3,2,1,0]。
- i i i和 j j j可以超出列表的元素范围,不会报错,只是超出范围的元素不会被加入切片中。