功能修改清单 [英] Function modifies list

查看:73
本文介绍了功能修改清单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆