2014-01-22 225 views
1

我在Python中发现了一些我无法解释的奇怪行为。我写了以下功能:替换输入变量的Python函数

def process_data(data_in, unique_recs_in): 
    recs = unique_recs_in 
    for x, dat in enumerate(recs): 
     recs[x].append(data_in.count(dat)) 
    return recs 

其中data_in和unique_recs_in是列表的列表。 'data_in'计数表示受体,每次在每个受体中都存储一个列表,失败的标记。 'Unique_recs_in'是所有唯一受体位置的列表。

我无法弄清楚的是,当我调用这个函数时,我的输出'recs'会正确返回。但是,当我运行该函数时,'unique_recs_in'发生了变化,并且与'recs'相同。我有错误测试了代码,并且可以确认它发生在这个函数中。有人有主意吗?

编辑:下面

样品输入DATA_IN

[['631507.40000', '4833767.20000', '60.00'], ['631507.40000', '4833767.20000', '63.00'], ['631507.40000', '4833767.20000', '66.00']] 

unique_recs_in:

[['631552.90000', '4833781.00000', '24.00'], ['631569.50000', '4833798.80000', '48.00'], ['631589.20000', '4833745.50000', '12.00']] 
+0

你能给一些示例输入/输出这说明什么问题? – wnnmaw

回答

3

recs = unique_recs_in只是简单地为列表对象创建一个新的引用,以获得列表清单的全新副本,使用copy.deepcopy

>>> lis = [[1, 2], [3, 4]] 
>>> a = lis 
>>> a.append(4)  #changes both `a` and `lis` 
>>> a, lis 
([[1, 2], [3, 4], 4], [[1, 2], [3, 4], 4]) 

即使是一个浅拷贝是不够的名单列表:

>>> a = lis[:] 
>>> a[0].append(100) #Inner lists are still same object, just the outer list has changed. 
>>> a, lis 
([[1, 2, 100], [3, 4]], [[1, 2, 100], [3, 4]]) 

copy.deepcopy返回一个全新的副本:

>>> import copy 
>>> a = copy.deepcopy(lis) 
>>> lis 
[[1, 2, 100], [3, 4], 4] 
>>> a.append(999) 
>>> a, lis 
([[1, 2, 100], [3, 4], 4, 999], [[1, 2, 100], [3, 4], 4]) 
>>> a[0].append(1000) 
>>> a, lis 
([[1, 2, 100, 1000], [3, 4], 4, 999], [[1, 2, 100], [3, 4], 4]) 

如果列表中包含唯一不变的对象,然后只浅拷贝就足够了:

recs = unique_recs_in[:] 

您可能会发现这是很有帮助的还有:Python list([]) and []

+0

我从来不知道这一点;去搞清楚。感谢您的示例代码,这真的很有帮助。 – HHains

2

你可能会想在recs存储一个复制的unique_recs_in所以它不会被修改。试试这个:

recs = [l[:] for l in unique_recs_in] # although Ashwini `deepcopy` is more elegant 

通过另一个列表l1=l2你只是建立和别名它们之间分配列表(即:两个变量引用内存中的同一个列表),以便修改一个将修改其他(因为他们是一样的)。

希望这会有所帮助!

+1

这将产生一个浅拷贝,它不会完全分开这两个。例如,追加到'recs [x]'仍然会影响'unique_recs_in'的第x个值 – Kevin

+0

@Kevin好点,我错过了,可能不是OP想要的,我会修改答案。谢谢! –