【问题标题】:changing the value of lists as function arguments将列表的值更改为函数参数
【发布时间】:2016-12-19 12:05:35
【问题描述】:

我知道当将列表作为参数发送给函数时,函数的变化会改变列表,例如:

p=[[3, 4], [2, 3]]
node=[5,3]

def foo(node, p_as_list):
    p_as_list.append(node)


foo(node, p)
print(p) #p changes

停止我使用 copy() 的更改:

p=[[3, 4], [2, 3]]
node=[5,3]

def foo(node, p_as_list):
    p_as_list.append(node)

#this line
foo(node, p.copy())
print(p) # without changes

但如果我像这样更改函数:

p=[[3, 4], [2, 3]]
node=[5,3]

def foo(node, p_as_list):
    #this line
    p_as_list=p_as_list[-1]
    p_as_list.append(node)

foo(node, p.copy())
print(p) 

p又变了,我不明白为什么会这样?

【问题讨论】:

  • 这是因为你做的是浅拷贝,而不是深拷贝。您正在复制对那些仍被修改的内部列表的引用。见What is the difference between a deep copy and a shallow copy?
  • 我需要一种高效的内存方式来将列表传递给函数,并且我需要不改变列表,有没有更好的解决方案?
  • 我不确定您的具体情况,但您可以尝试仅复制正在修改的列表的一部分。例如,如果您已完成p_as_list=p_as_list[-1].copy(),则原始列表将保持不变,并且您不会浪费内存来复制原始列表的各个方面。您甚至可以删除传递给函数的 p.copy() 部分。

标签: python parameter-passing


【解决方案1】:

插入一些调试prints 有助于识别问题:

p=[[3, 4], [2, 3]]
node=[5,3]

def foo(node, p_as_list):
    #this line
    print('p', id(p_as_list))
    p_as_list=p_as_list[-1]
    print('pm1', id(p_as_list))
    p_as_list.append(node)

print('p', id(p))
print('pm1', id(p[-1]))
foo(node, p.copy())
print(p) 

打印出来:

p 1872370555144 
pm1 1872370556232
p 1872370108872
pm1 1872370556232
[[3, 4], [2, 3, [5, 3]]]

注意p[-1]id 没有改变,你操作的是同一个list。那是因为你只在使用list.copy()时创建了一个浅拷贝

我建议您只复制您在函数中修改的部分,而不是copying 整个列表:

p=[[3, 4], [2, 3]]
node=[5,3]

def foo(node, p_as_list):
    #this line
    p_as_list=p_as_list[-1].copy()  # copy here!
    p_as_list.append(node)

foo(node, p)  # don't copy here!
print(p) 

【讨论】:

    【解决方案2】:

    一种方法是使用 deepcopy

    参考库路径:https://docs.python.org/2/library/copy.html

    import copy
    
    p = [[3, 4], [2, 3]]
    node = [5,3]
    
    def foo(node, p_as_list):
        p_as_list = p_as_list[-1]
        p_as_list.append(node)
    
    foo(node, copy.deepcopy(p))
    
    print(p)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-14
      • 2013-09-04
      • 2013-10-21
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      相关资源
      最近更新 更多