这是我输入的代码。这里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
答案 0 :(得分:5)
请注意,在p1
中,您不将值分配给list1
,这是p1
本地变量的名称。实际上,您正在list
分配list1
对象引用的的第一个元素,这与list
引用的li
对象相同。封闭范围。
另一方面,在p2
,i+=10
为本地变量i
分配值,而不是变量int1
封闭范围。这是因为类型为+=
的对象上的int
运算符实际上并未修改对象,而是返回一个新对象。 (也就是说,对于int
,i+=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
语句设置第一个单元格列表以引用1000
。 li
在整个修改过程中仍然指向此列表,在函数返回后,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的列表行为,我猜你只需要把它放在一个列表中。