当我有类似的功能时
def foo(A):
tmp=A
tmp=tmp+1
*rest of the function*
return
或者
def foo(A):
global tmp
tmp=A
tmp=tmp+1
*rest of the function*
return
“A”和“tmp”都添加 1 而不仅仅是“tmp”。我做错了什么,我该如何解决?
当我有类似的功能时
def foo(A):
tmp=A
tmp=tmp+1
*rest of the function*
return
或者
def foo(A):
global tmp
tmp=A
tmp=tmp+1
*rest of the function*
return
“A”和“tmp”都添加 1 而不仅仅是“tmp”。我做错了什么,我该如何解决?
正如 nneonneo 在 Blake 的回答(描述了问题的重要部分)下的评论所说,原始帖子中的代码实际上并没有按照他所说的那样做。例如:
def foo(A):
tmp = A
tmp = tmp + 1
return (A, tmp)
foo(3)
返回(3,4)
,表示 A 保持不变。
这不正确的地方是 A 是可变类型。可变类型包括列表、字典和它们的派生类型,而整数、浮点数和元组是不可变的。
例如:
def foo(A):
tmp = A
tmp[0] = tmp[0] + 1
return (A, tmp)
foo([1, 2])
返回([2, 2], [2, 2])
,在这种情况下 A 已更改。
foo 在列表情况下更改 A 的值,但在整数情况下没有更改,因为列表是可变的,而整数不是。当 A 是可变类型时将 A 分配给 tmp 会分配对可变对象的引用,并且更改其元素之一(如tmp[0] = tmp[0] + 1
)不会生成新对象。
例如,如果您不希望您的函数对列表具有这种类似副作用的行为,一个常见的 Python 习惯用法是使用切片表示法来复制列表。当您将它分配给 tmp 时,这将创建一个新的列表对象,它是 A 中列表对象的副本:
def foo(A):
tmp = A[:]
# this slice makes a new list, a copy of A
tmp[0] = tmp[0] + 1
return (A, tmp)
foo([1, 2])
这将返回([1, 2], [2, 2])
,因此 A 未更改,而 tmp 已更改。
还有其他方法可以复制彼此细微不同的列表或其他可变对象。 如何克隆或复制列表?对您的选择有很好的描述。
那是因为 python 方法参数是按引用传递的,而不是按值传递的。您实际上是在修改内存中的同一个位置,两个不同的变量指向。
>>> def foo(a):
tmp = a
print(tmp, a, id(a), id(tmp))
>>> foo(5)
5 5 505910928 505910928
>>> b = 5
>>> foo(b)
5 5 505910928 505910928
>>> id(b)
505910928
并以全球为例:
>>> def foo(a):
global tmp
a = tmp
print(a, tmp, id(a), id(tmp))
>>> foo(5)
7 7 505910960 505910960
>>> foo('s')
7 7 505910960 505910960
>>> tmp
7
>>> tmp = 6
>>> foo('a')
6 6 505910944 505910944