2016-05-30 35 views
2

我正在体验一种从我听到的在Python中很常见的行为,但我想知道这是默认设置,以及如何防止这种情况。请看下面的代码:从外部函数里面改变外部字典的Python

dic1 = {'a':1, 'b':2} 
lis1 = [1, 2] 

def somefunc(dic): 
    dic.update({'b':20}) 
    return dic 

def otherfunc(lis): 
    lis.append(20) 
    return lis 

for i in range(3): 
    dic2 = dic1 
    lis2 = lis1 
    print(dic2) 
    somefunc(dic2) 
    print(lis2) 
    otherfunc(lis2) 

我们运行此代码,它输出

{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 20} 
[1, 2, 20] 
{'a': 1, 'b': 20} 
[1, 2, 20, 20] 

但为什么没有输出以下?

{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 2} 
[1, 2] 

我觉得它应该输出这一点,因为我重新dic2lis2。为什么这是默认行为?一旦进入函数,Python不应该复制dic2吗?不应该dic2=dic1创建一个dic1的副本,而不是创建一个指向内存中相同位置的不同指针? (如果这确实发生了什么)

我可以通过更换dic2 = dic1dic2 = dic1.copy()(或添加dic=dic.copy()的功能)防止此问题与dic1发生,但我怎么用列表做呢?他们没有复制方法。此外,有没有办法让我在默认情况下防止这种情况发生,而不必在每次处理函数内的字典(或者甚至Pandas数据框等)时都记得使用复制方法?

干杯

+0

Python中的所有值都通过引用传递。有关更完整的解释,请参阅http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference。 – jstlaurent

回答

1

在Python中,列表是可变的,这意味着LIS2是LIS1的另一个名称而已,因此它们是同一个对象

这里有2种方式,使上LIS2 LIS1的副本:

lis2 = lis1[:] 

lis2 = list(lis1) 

我宁愿用list()因为它更具有可读性。