这是一个将矩阵顺时针旋转90度的问题,我不明白为什么我不能使用:
matrix = zip(*matrix[::-1])
但是:
class Solution:
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: void Do not return anything, modify matrix in-place instead.
"""
matrix[::] = zip(*matrix[::-1])
答案 0 :(得分:3)
matrix
是对矩阵对象的引用。分配给matrix
将更改matrix
以引用您新创建的对象,但不会更改原始对象的内容。 matrix[::] =
在__setitem__
所引用的对象上调用matrix
,从而相应地更改了对象的内容。
答案 1 :(得分:1)
在Python中,所有分配都将引用绑定到名称。运算符调用现有引用的方法 1 。就您而言,声明
matrix = ...
纯粹是赋值 2 。它计算右侧,并将其绑定到本地函数作用域中的名称matrix
。传递时引用的对象matrix
均保持不变。
这就是为什么您看不到所做更改的原因。并不是说该功能不能以这种方式工作,而是对旋转后的列表没有任何作用。该函数退出后,数据将被丢弃。
操作
matrix[:] = ...
另一方面,尽管有=
符号 3 ,但并不是语义上的赋值。这是对matrix.__setitem__(...)
4 的调用。与其他任何方法一样,__setitem__
方法可以直接在对象上操作,而无需更改其名称绑定。
就索引而言,[:]
等同于[::]
。它们分别是[0:len(matrix)]
和[0:len(matrix):1]
的简写。在这两种情况下,都将使用默认步长。通常,任何包含冒号的索引都将转换为slice
对象。缺少的元素设置为None
,并替换为此处显示的特定于序列的默认值。
1 某些操作符(例如+=
)在调用方法后执行分配。这些称为augmented assignments。但这不是我们现在感兴趣的情况。
2 除了文字assignment statements(=
)之外,其他一些类型的赋值是def
(将功能对象绑定到其名称),{{ 1}}(对类对象的作用相同),class
(将模块或模块的元素绑定到名称),将参数传递给函数(将对象绑定到局部参数名称或kwarg)字典键)和import
(在每次迭代时将元素从迭代器绑定到循环变量)。
3 从解析器的角度来看,它仍然是assignment,但是对语句的处理完全不同。类似的语句(实际上不是分配)是在实现为描述符的属性(例如for
)上使用=
运算符。
4 从技术上讲,它更等效于property
,但还有一些其他优化。例如,将永远不会搜索type(matrix).__setitem__(matrix, ...)
的元类。