python: 在子例程中更改列表值

python: changing list value in sub-routine

我有一个简单的例子。 函数 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)

输出:

['first', 'another one', 'the last one']

您需要 return ["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()

请注意,实际上您不需要这里的功能!!!你可以在第一个函数中做这个赋值。

您的 test_list_change2 程序正在执行 lst = ['the very last one']。它只是将一个新对象分配给本地名称 lst。它对传递给该过程的列表没有任何影响。

我不确定你想要完成什么。如果你想 test_list_change2 添加到 lst,只需附加它。你能澄清一下吗?

你需要实际改变原来的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']

您可以随心所欲地操作列表,但您需要实际引用原始列表对象,重新分配名称不会更改 lst,它只会将该名称分配给另一个对象。

如果您只想 "the very last one" 出现在列表中,那么:

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)

您可能对 python 和 "passing by reference" 的工作方式感到困惑,并认为既然它是通过引用传递的,那么原始列表应该更新为 ["the very last one"]。

它的工作方式如下:

1) 在 test_list_change 被调用之前,有一个名字 "string_list" 和 python 创建一个对象 ["first", "another one"] 被赋值至 string_list

2) 现在在 test_list_change 中,新名称 "lst" 被分配 ["first"、"another one"]。所以现在两个名字都分配了同一个对象。然后附加并更改为 ['first'、'another one'、'the last one'],由 string_list 和 lst

指向

3) 在test_list_change_2中,在赋值之前,存在另一个指向["first"、"another one"、'ths last one']的本地lst name。然后 python 创建另一个对象 ['the vary last one'] 并替换本地 lst 变量的值。

4) string_list 仍然指向 ['first', 'another one', 'the last one']

换句话说,变量只是传递的名称,对象是管理的 'by reference'。