3
def f(x, y):
   x.append(x.pop(0))
   x.append(y[0])
   return x

a = [4,5]
b = [1,2,3]
w = f(a,b) + f(a,b)

w 结果是 [4,1,5,1,4,1,5,1] 但是,如果我手动检查代码(在我的脑海中),我会得到 [5,4,1,4,1,5 ,1]

为什么是这样?

f(a,b) = [5,4,1] 对吗?那么 a 将是 = [5,4,1] 和 b = [1,2,3]。

那么 f(a,b) = [4,1,5,1] 这将是: [5,4,1] + [4,1,5,1] = [5,4,1,4,1 ,5,1] 不是 [4,1,5,1,4,1,5,1]

为什么代码会改变这个?尝试自己运行代码时我做错了什么?

4

3 回答 3

6

两个调用都返回相同的列表,即绑定到的对象a,导致第二个返回值(仍然是绑定到的对象a)被添加到自身。该函数只改变列表,从不替换它。

于 2013-11-07T05:24:33.357 回答
3

您的问题是您的代码既更改了原始列表,又返回了对它的引用。当您第二次调用f时(切勿使用单字母名称!!!)您也会更改原始调用的结果。让我们分阶段进行:

n [53]: a1 = f(a,b)

In [54]: a
Out[54]: [5, 4, 1]

In [55]: a2 = f(a,b)

In [56]: a2
Out[56]: [4, 1, 5, 1]

In [57]: a
Out[57]: [4, 1, 5, 1]

这说明了我的观点(函数id返回对对象的引用)

In [77]: id(a)
Out[77]: 145114860

In [78]: id (f(a,b))
Out[78]: 145114860

如您所见,您的函数有副作用。如果你这样重写

def f(x, y):
    x.append(x.pop(0))
    x.append(y[0])
    return copy(x)

第二次调用不会影响第一次调用的结果 -

In [74]: id(a)
Out[74]: 145114860

In [75]: id (f(a,b))
Out[75]: 145113356

结果将是 [5, 4, 1, 4, 1, 5, 1]

于 2013-11-07T05:38:14.290 回答
0

f(a,b) = [5,4,1] 对吗?那么 a 将是 = [5,4,1] 和 b = [1,2,3]。

全部正确。然而。如果你看看f正在做什么,它只是返回变异的x(即 mutating a)。所以做两次

f(a,b)
Out[40]: [5, 4, 1]

a
Out[41]: [5, 4, 1]

f(a,b)
Out[42]: [4, 1, 5, 1]

a
Out[43]: [4, 1, 5, 1]

然后将其与自身连接。就是这样w:只是a + a,经过a两次变异。

于 2013-11-07T05:40:24.983 回答