В чем разница между list [::] и list? - PullRequest
0 голосов
/ 17 сентября 2018

Это вопрос поворота матрицы на 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])

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

В Python все назначения связывают ссылку на имя.Операторы вызывают метод существующей ссылки 1 .В вашем случае утверждение

matrix = ...

является просто заданием 2 .Он вычисляет правую часть и привязывает его к имени matrix в локальной области действия функции.Какой бы объект matrix ни упоминался, когда вы его передали, остается нетронутым.

Вот почему вы не видите сделанные вами изменения.Дело не в том, что функция не работает таким образом, а в том, что она ничего не делает с повернутым списком.Данные отбрасываются при выходе из функции.

Операция

matrix[:] = ...

, с другой стороны, является , а не назначением в семантическом смысле, несмотря на = символ 3 .Это звонок на matrix.__setitem__(...) 4 .Метод __setitem__, как и любой другой метод, работает непосредственно с объектом, не изменяя его привязки имен.

Что касается индексации, [:] эквивалентно [::].Они сокращены для [0:len(matrix)] и [0:len(matrix):1] соответственно.В обоих случаях будет использоваться размер шага по умолчанию.Как правило, любой индекс с двоеточиями в нем будет преобразован в объект slice.Отсутствующие элементы устанавливаются на None и заменяются значениями по умолчанию для определенной последовательности, показанными здесь.


1 Некоторые операторы, такие как +=, выполняют назначение после вызова метода.Они называются расширенные задания .Но это не тот случай, который нас сейчас интересует.

2 Помимо литеральных операторов присваивания (=), некоторые другие типы присваиваний def (который связывает объект функции с его именем), class (который делает то же самое для объекта класса), import (который связывает модуль или элемент модуля с именем), передавая аргументы функции (который связывает объекты с локальными именами аргументов или ключами словаря kwarg) и for (который связывает элемент из итератора с переменной цикла на каждой итерации).

3 Это все еще присваивание с точки зрения синтаксического анализатора, но оператор обрабатывается совершенно иначе.Аналогичное утверждение, которое на самом деле не является присваиванием, использует оператор = для атрибута, реализованного в качестве дескриптора, такого как property.

4 Технически, это скорееэквивалентно type(matrix).__setitem__(matrix, ...), но с некоторыми дополнительными оптимизациями.Например, метакласс type(matrix) никогда не будет найден.

0 голосов
/ 17 сентября 2018

matrix в вашем методе является ссылкой на матричный объект. Присвоение matrix изменит matrix на ссылку на вновь созданный объект, но не изменит содержание исходного объекта. matrix[::] = вызывает __setitem__ для объекта, на который ссылается matrix, что соответственно изменяет содержимое объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...