python: изменение значения списка в подпрограмме

У меня есть простой пример. Функция test_list_change должна изменить список, переданный ей в качестве параметра. И внутри этой функции есть вызов подпрограммы test_list_change_2, которая должна изменить тот же список.

Проблема в том, что список результатов не содержит изменений, внесенных подпрограммой test_list_change_2

Почему это может быть?

Вот пример:

def test_list_change(lst):
    if len(lst) < 3:
        lst.append("the last one")
        test_list_change_2(lst)

def test_list_change_2(lst):
    lst = ["the very last one"]

string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)

Выход:

["первый", "еще один", "последний"]

5 ответов

Решение

Вам нужно на самом деле изменить оригинал list/object:

def test_list_change(lst):
    if len(lst) < 3:
        lst.append("the last one")
        test_list_change_2(lst)

def test_list_change_2(lst):
    lst[:] = ["the very last one"] # changes original list object

string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
['the very last one']

Если вы хотите изменить вокруг элементов:

def test_list_change_2(lst):
    lst[:-1] = ["the very last one"]
    lst[:] = lst[::-1]

string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
['the last one', 'the very last one']

Вы можете манипулировать списком любым удобным для вас способом, но на самом деле вам нужно обратиться к исходному объекту списка, переназначение имени не изменится, а просто назначит это имя другому объекту.

Возможно, вы запутались в том, как все работает в python с "передачей по ссылке", и подумали, что, поскольку он передается по ссылке, исходный список следует обновить до ["самого последнего"].

Это работает следующим образом:

1) перед вызовом test_list_change существует имя "string_list", и python создает объект ["first", "another one"], который назначается для string_list

2) теперь в test_list_change новому имени "lst" присваивается ["first", "another one"]. Так что теперь обоим именам присвоен один и тот же объект. Затем он добавляется и изменяется на ['first', 'another', 'last one'], на который указывают string_list и lst

3) В test_list_change_2 перед выполнением назначения существует другое локальное имя lst, которое указывает на ["first", "another one", "ths last one"]. Затем python создает другой объект ['var last one'] и заменяет значение локальной переменной lst.

4) string_list по-прежнему указывает на ['first', 'another', 'last' ']

Иными словами, переменные - это просто передаваемые имена, а объекты управляются "по ссылке".

Ваш test_list_change2 процедура делает lst = ['the very last one'], Это просто присвоение нового объекта локальному имени lst, Это никак не влияет на список, переданный этой процедуре.

Я не уверен, что вы пытаетесь достичь. Если ты хочешь test_list_change2 добавить к lstПросто добавь это. Вы можете уточнить?

Вам нужно вернуть ["the very last one"] в test_list_change_2:

def test_list_change_2():
    return ["the very last one"]

и назначить результат функции lst в первой функции:

def test_list_change(lst):
    if len(lst) < 3:
        lst.append("the last one")
        lst= test_list_change_2()

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

Если вы пытаетесь включить в список только "самого последнего", то:

def test_list_change(lst):
    if len(lst) < 3:
        lst.append("the last one")
    lst = test_list_change_2(lst)

def test_list_change_2(lst):
    for i in range(len(lst)):
        lst.pop()
    lst.append("the very last one")


string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
Другие вопросы по тегам