Могу ли я не изменить список внутри функции? - PullRequest
0 голосов
/ 19 ноября 2018
# left rotate using slicing
def leftRotate(arr, k, n):
    arr = arr[k:] + arr[:k]
    print(arr)

arr = [1, 2, 3, 4, 5, 6, 7] 
leftRotate(arr, 2, 7) 
print(arr)

Результат:

[3, 4, 5, 6, 7, 1, 2]
[1, 2, 3, 4, 5, 6, 7]

Когда я печатаю массив вне функции, он больше не вращается и остается таким, каким он был изначально. Может ли кто-нибудь помочь мне понять это?

Ответы [ 4 ]

0 голосов
/ 19 ноября 2018

Есть много действительно сложных ответов. Вот версия "для чайников":

  • Вы передаете arr в leftRotate()
  • Практически для всех целей вы можете думать об этом как о создании другой переменной , также называемой arr, с которой работает leftRotate(). leftRotate() arr - это не то же самое , что и arr, который вы передаете в leftRotate(). Это является копией (технически это не копия, пока вы не назначите arr чему-то другому, но достаточно близко для этих целей).
  • Вы больше не получите ваш модифицированный arr из leftRotate().

Вы можете решить это двумя способами:

  • Определите arr вне leftRotate() и не пропускайте arr in. Я назову этот подход "global". Не рекомендуется, если у вас нет очень веских причин.
  • Используйте return arr после завершения вашей функции. По сути, return 'x' означает leftRotate() == 'x'. В 99,9999% случаев это то, что вы хотите.

Следовательно, в вашем примере, что вы действительно хотите, это:

#left rotate using slicing
def leftRotate(arr, k, n):
    arr=arr[k:]+arr[:k] # not sure this is right, but once you get the return working, it should be easy to debug
    # print arr # changed
    return arr

arr = [1, 2, 3, 4, 5, 6, 7] 
# leftRotate(arr, 2, 7) # changed
arr = leftRotate(arr, 2, 7) 
print arr
0 голосов
/ 19 ноября 2018

Да, вы можете изменить список внутри функции, но вам нужно использовать правильный синтаксис.Как вы уже видели, это не правильный путь:

def leftRotate(arr, k, n):
    arr = arr[k:] + arr[:k]

Я постараюсь объяснить, почему это не сработало, и надеюсь дать вам лучшую интуицию о том, что на самом деле происходит.Внутри области действия функции, показанной выше, есть 3 локальные переменные: arr, k и n.Операции с правой стороны arr[k:] + arr[:k] создают новый объект списка без изменения исходного списка, и этот результирующий объект привязывается к имени локальной переменной arr.Это не изменяет исходный объект, потому что такие операторы присваивания в Python являются никогда мутирующими объектами.Они будут связывать только имя в пространстве имен. Думайте об этом, как будто вы берете тег имени "arr" из старого объекта списка , который был передан в качестве аргумента , и прикрепляете его к новому объекту списка , который былтолько что создан.Старый объект списка не модифицируется такой операцией, изменяется только локальное пространство имен - старый объект списка становится «анонимным» и более недоступен в этой области.

Решение состоит в том, чтобы использовать другой видоператора присваивания, присваивание среза , которое действительно мутирует:

def leftRotate(arr, k, n):
    arr[:] = arr[k:] + arr[:k]

В качестве последнего примечания в stdlib есть структура данных в виде списка, которая обеспечивает более эффективные операции ротации (пристоимость менее эффективной индексации в середине коллекции).Если вы заинтересованы в этом, прочитайте документы по collections.deque.

0 голосов
/ 19 ноября 2018

Ваша проблема в том, что вы не можете изменить переменную внутри функции python из-за области видимости. Прочтите это для получения дополнительной информации.

Но возобновив, вам нужно либо вернуть arr и присвоить его снаружи.Например:

#left rotate using slicing
def leftRotate(arr, k, n):
    arr=arr[k:]+arr[:k]
    return arr

arr = [1, 2, 3, 4, 5, 6, 7] 
arr = leftRotate(arr, 2, 7) 
print arr

Или, если хотите, вы можете сделать arr глобальным.(Проверьте это для получения дополнительной информации об этом).(Не рекомендую этот последний, но существует)

arr = [1, 2, 3, 4, 5, 6, 7]

#left rotate using slicing
def leftRotate( k, n):
    global arr
    arr=arr[k:]+arr[:k]

leftRotate( 2, 7) 
print arr

Надеюсь, это помогло:)

0 голосов
/ 19 ноября 2018

Проблема заключается в том, что нарезка списка не применяется на месте.По сути, создается список новый , который назначается переменной arr в области leftRotate, т. Е. К нему можно получить доступ только в вашей функции.Метод, который работает вместо , будет работать должным образом:

def rev_sort(arr, k, n):
    arr.sort(reverse=True)
    print(arr)

arr = [1, 2, 3, 4, 5, 6, 7] 
rev_sort(arr, 2, 7) 

print(arr)

[7, 6, 5, 4, 3, 2, 1]
[7, 6, 5, 4, 3, 2, 1]

В вашем примере ваша функция может вернуть список и присвоить ему arr:

def leftRotate(arr, k, n):
    arr = arr[k:]+arr[:k]
    print(arr)
    return arr

arr = [1, 2, 3, 4, 5, 6, 7] 
arr = leftRotate(arr, 2, 7) 
print(arr)

[3, 4, 5, 6, 7, 1, 2]
[3, 4, 5, 6, 7, 1, 2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...