功能修改清单 [英] Function modifies list
问题描述
def make_Ab(A,b):
n = len(A)
Ab = list(A)
for index in range(0,n):
Ab[index].append(b[index][0])
print(A)
return Ab.copy()
A = [[0.0, 1.0, 1.0, 2.0], [1.0, 3.0, 1.0, 5.0], [2.0, 0.0, 2.0, 4.0]]
b = [[1],[2],[3]]
print(A)
[[0.0,1.0,1.0,2.0],[1.0,3.0,1.0,5.0],[2.0,0.0,2.0,4.0]]
Ab = make_Ab(A,b)
print(A)
[[0.0,1.0,1.0,2.0,1],[1.0,3.0,1.0,5.0,2],[2.0,0.0,2.0,4.0,3]]
我不明白为什么我的函数会修改原始列表.我没有将 A
指定为函数的全局变量(我什至试图在其他函数中声明它,因此它不会是全局的),我也没有通过引用传递它(例如 Ab = A
).有什么问题吗?
I don't get why does my function modify my original list. I didn't specifyA
as global in function (I've even tried to declare it in a different function so it won't be global), I didn't pass it through reference (like Ab = A
). What's the problem?
推荐答案
这里的问题是,当您不修改变量时(如果没有 global则不能这样做)
),您正在修改值.
The issue here is that, while you're not modifying the variable (which you can't do without global
), you are modifying the value.
起初这可能有点令人困惑.这两个看起来像是在做同样的事情:
This can be a bit confusing at first. These two look like they do the same thing:
>>> a = [1, 2, 3]
>>> a = a + [1]
>>> a
[1, 2, 3, 1]
>>> a = [1, 2, 3]
>>> a.append(1)
>>> a
[1, 2, 3, 1]
但事实并非如此.第一个是从 a
和 [1]
中创建一个新列表,然后将该新列表绑定回名称 a
.如果对同一列表有其他引用,它将保持不变.另一方面,第二个是更改 a
命名的实际列表对象.如果对同一列表有其他引用,它将更改.
But they're not. The first one is making a new list out of a
and [1]
and then binding that new list back to the name a
. If there was some other reference to that same list, it would be unchanged. The second one, on the other hand, is changing the actual list object that a
names. If there was some other reference to that same list, it would change.
>>> a = [1, 2, 3]
>>> b = a
>>> a = a + [1]
>>> b
[1, 2, 3]
>>> a = [1, 2, 3]
>>> b = a
>>> a.append(1)
>>> b
[1, 2, 3, 1]
第二个代码是您在代码中所做的,更改了列表对象的值.这意味着,对该列表对象的每个引用,甚至是您无权访问的名称,都将看到更改.
What you're doing in your code is the second one, changing the value of the list object. Which means that every reference to that list object, even a name you don't have access to, will see the change.
但是您不是在修改 A
本身,而是在修改 list(A)
.那不应该是列表的新副本吗?
But you're not modifying A
itself, you're modifying list(A)
. Shouldn't that be a new copy of the list?
是的-但是,即使 Ab
是与 A
不同的列表, Ab [0]
仍然是相同列表为 A [0]
.您已经创建了一个新列表,该列表引用了与原始列表相同的子列表.因此,当您对这些子列表进行变异时…是同样的问题.
Yes, it is—but, even if Ab
is a different list from A
, Ab[0]
is still the same list as A[0]
. You've made a new list that references the same sublists as the original one. So when you mutate those sublists… same problem.
如果要更改此设置,可以执行以下两项操作之一:
If you want to change this, you can do one of two things:
- 在函数顶部复制所有子列表以及列表,因此您可以更改副本而不是原始副本.
- 不要在列表上使用任何变异操作;建立一个新的.
第一个是一个简单的更改:用 Ab = copy.deepcopy(A)
或 Ab = [列出[sub](用于Ab中的sub的子列表)
.
The first one is a simple change: instead of Ab = list(A)
, do Ab = copy.deepcopy(A)
or Ab = [list(sub) for sub in Ab]
.
第二个需要稍微重写代码:
The second one requires rewriting your code a bit:
def make_Ab(A,b):
n = len(A)
Ab = []
for index in range(0,n):
Ab.append(A[n] + [b[index][0]])
return Ab
(或者,当然,您可以将其重写为列表理解.)
(Or, of course, you can rewrite that as a list comprehension.)
这篇关于功能修改清单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!