Reputation: 868
This is the code I type. Here the value of int has not changed outside of function but value of list has changed.I was expecting the value of list will not change. What is the reason?
>>> 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
Upvotes: 0
Views: 62
Reputation: 530940
Note that in p1
, you are not assigning a value to list1
, which is the name of a variable local to p1
. You are actually assigning to the first element of the list
object referenced by list1
, which is the same list
object referenced by li
in the enclosing scope.
In p2
, on the other hand, i+=10
does assign a value to the local variable i
, not the variable int1
in the enclosing scope. This is because the +=
operator on objects of type int
do not actually modify the object, but return a new object instead. (That is, for an int
, i+=10
is equivalent to i = i + 10
.)
Just to show that +=
can operate on the underlying object directly, consider this function:
def p3(list1):
list1 += [10]
Then run it on a list:
>>> foo = [1,2,3]
>>> p3(list1)
>>> foo
[1, 2, 3, 10]
Here, the call list1 += [10]
is really equivalent to list1.extend([10])
, not list1 = list1 + [10]
, due to how list.__iadd__
is defined. Here, you are again not assigning a value to the name list1
, but rather invoking a method on the object referenced by list1
(which is the same object referenced by foo
).
(Update: as pointed out by user2357112, technically you do assign to list1
, but list.__iadd__
is designed to properly assign the same list back, so that the end result is that you still have a reference to the same mutable object you started with.)
Upvotes: 5
Reputation: 11080
A list is like a pointer to a list object.
#For example
a =[0,0]
b = a
b[0]=1
resulting in
b
[1,0]
Where as an int is an a different beast
#For Example
a = 0
b = a
b +=1
resulting in
a
1
to get the int behaviour from a listyou can make a clone of a list by passing it to list()
#for example
a = [0,0]
b = list(a)
b[0]=1
resulting in
a
[0,0]
and if you want the list behaviour from an int I guess you would have to just put it in a list.
Upvotes: -1
Reputation: 280251
Assigning to a variable, like i+=10
, is an operation on a variable, while index assignment, like list1[0]=1000
, is an operation on the object a variable refers to.
When you call p2(int1)
, the local variable i
gets set to refer to the int int1
referred to, and then the i+=10
statement redirects i
to refer to a new, larger integer. int1
still refers to the old integer.
When you call p1(li)
, the local variable list1
gets set to refer to the list li
referred to, and then the list1[0]=1000
statement sets the first cell of the list to refer to 1000
. li
still points to this list throughout the modification, and after the function returns, li
still reflects the change.
(There's another complexity here in that +=
also requests that an object mutate itself if it's mutable, in addition to performing an assignment, but that doesn't come up in this code.)
Upvotes: 3