为什么python参数有时会改变?

时间:2015-04-25 04:55:30

标签: python python-2.7

这是我输入的代码。这里int的值没有在函数之外改变,但是list的值已经改变了。我期待list的值不会改变。是什么原因?

>>> def p1(list1):
    list1[0]=1000

>>> def p2(i):
    i+=10

>>> li=[1,2,3,4,5]
>>> int1=10
>>> p1(li)
>>> p2(int1)
>>> li
[1000, 2, 3, 4, 5]
>>> int1
10

3 个答案:

答案 0 :(得分:5)

请注意,在p1中,您将值分配给list1,这是p1本地变量的名称。实际上,您正在list分配list1对象引用的的第一个元素,这与list引用的li对象相同。封闭范围。

另一方面,在p2i+=10 为本地变量i分配值,而不是变量int1封闭范围。这是因为类型为+=的对象上的int运算符实际上并未修改对象,而是返回一个新对象。 (也就是说,对于inti+=10相当于i = i + 10。)

只是为了表明+= 可以直接对基础对象进行操作,请考虑以下函数:

def p3(list1):
    list1 += [10]

然后在列表中运行它:

>>> foo = [1,2,3]
>>> p3(list1)
>>> foo
[1, 2, 3, 10]

此处,由于list1 += [10]的定义方式,调用list1.extend([10])实际上等同于list1 = list1 + [10],而不是list.__iadd__。在这里,您再次没有为名称list1分配值,而是在list1引用的对象上调用方法(与foo引用的对象相同)。

(更新:正如user2357112指出的那样,技术上你分配给list1,但list.__iadd__旨在正确地分配相同的列表,以便结束结果是你仍然引用了你开始使用的同一个可变对象。)

答案 1 :(得分:3)

分配给变量(如i+=10)是对变量的操作,而索引赋值(如list1[0]=1000)是对变量引用的对象的操作。

当您致电p2(int1)时,本地变量i设置为引用所引用的int int1,然后i+=10语句重定向i引用一个新的更大的整数。 int1仍然引用旧的整数。

当您调用p1(li)时,局部变量list1被设置为引用所引用的列表li,然后list1[0]=1000语句设置第一个单元格列表以引用1000li在整个修改过程中仍然指向此列表,在函数返回后,li仍然反映了更改。

(这里有另一个复杂性,+=除了执行赋值之外,还要求对象变异,如果它是可变的,但是这个代码中没有出现。)

答案 2 :(得分:-1)

列表就像是指向列表对象的指针。

#For example
a =[0,0]
b = a
b[0]=1

导致

b 
[1,0]

int是一个不同的野兽

#For Example
a = 0
b = a
b +=1

导致

a 
1

从列表中获取int行为你可以通过将列表传递给list()

来复制列表
#for example
a = [0,0]
b = list(a)
b[0]=1

导致

a
[0,0]

如果你想要一个int的列表行为,我猜你只需要把它放在一个列表中。