局部变量和全局变量之间的差异?

2024-09-28 17:21:05 发布

您现在位置:Python中文网/ 问答频道 /正文

Possible Duplicate:
Python passing list as argument

我找了很多关于这个的话题,但我不明白到底发生了什么。在

我有这个代码:

def altera(L1, L2):
    for elemento in L2:
        L1.append(elemento)
    L2 = L2 + [4]
    L1[-1] = 10
    del L2[0]
    return L2[:]

Lista1 = [1,2,3]
Lista2 = [1,2,3]

Lista3 = altera(Lista1, Lista2)

print Lista1
print Lista2
print Lista3

结果是:

^{pr2}$

我不明白Lista1是如何被修改的,而{}是如何被修改的。但是在测试代码之前,我认为Lista1和{}将保持不变,因为它们是全局变量。在


Tags: l1asargumentlistprint话题duplicatel2
3条回答

在Python中,列表是通过引用传递的。Lista1被修改,因为您直接调用.append

for elemento in L2:
    L1.append(elemento)

由于未修改列表,Lista2未被修改。您使用了加法运算符L2 = L2 + [4],它不修改L2。相反,它创建一个新列表并返回结果。在

如果你用Google搜索术语“passbyreference”,你应该能够在Python中找到一些很好的解释性示例。在

当您执行L1.append(elemento)时,您正在调用一个方法,该方法实际上更改了由变量L1命名的列表。其他所有设置L1L2值的命令实际上只是为新变量创建新名称。在

此版本不会更改任何内容:

def altera(L1, L2):
    for elemento in L2:
        # create a new list and assign name L1
        L1 = L1 + [elemento]
    # create a new list and assign name L2
    L2 = L2 + [4]
    return L2

Lista1 = [1,2,3]
Lista2 = [1,2,3]

Lista3 = altera(Lista1, Lista2)

print Lista1
print Lista2
print Lista3

而这一次:

^{pr2}$

但是L += [2]有一个棘手的问题,它与L = L + 2不完全相同。关于扩充赋值语句的Python Language Reference部分解释了这一区别:

An augmented assignment expression like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.”

在您的功能中有两种不同的情况:

def altera(L1, L2):
    for elemento in L2:
        L1.append(elemento)
        # [1] this ^ alters L1 in place
    L2 = L2 + [4]
    # [2] this ^ creates a new list
    L1[-1] = 10
    del L2[0]
    return L2[:]

要扩展我添加的内联注释:

  1. altera内,变量L1是您传入的任何内容(因此它是Lista1)。它不是一个拷贝,一个具有相同内容的新列表-它引用了相同的实际对象
  2. 当你分配L2 = L2 + [4]时,你要做两件事:

    1. 使用值L2 + [4]创建一个新列表
    2. 设置L2指向这个新列表,而不是您传入的任何内容

    如果我们重新命名变量,它将变得显式,并且工作方式与完全相同:

    ^{pr2}$

    或者,如果您想在适当的地方修改原始的L2(即,实际修改Lista2),您可以这样做

    L2.append(4)
    del L2[0]
    return L2[:]
    

    注意最后一行仍然意味着Lista3将是Lista2不同的列表对象,但它将具有相同的值。如果您只是return L2Lista3将与L2完全相同,因此它们将是同一列表对象的两个名称。

如果您想防止这种行为,可以如下调用altera

Lista3 = altera(Lista1[:], Lista2[:])

现在,在altera内部,它将处理自己的参数副本,并且不会影响原始的Lista1和{}。在

相关问题 更多 >