I'm trying to call a function defined outside of class scope in Python, and it modifies the passed value, without any references to the passed variable, but somehow the original variable in class scope gets modified.
I have used python extensively for scriting but haven't really done much with Classes. I looked at this post, which explains a lot but doesn't really talk about it. This variable is surely out of scope, how's it getting mutated?
def doSomethingOutOfScope(arr):
spv = arr[0]
arr[0] = 'S'
class Solution:
def doSomethingInScope(self, passed_arr):
print(passed_arr) # prints [0, 1, 2]
doSomethingOutOfScope(passed_arr) # passed_arr shouldn't get modified
print(passed_arr) # prints ['S', 1, 2] - Why ?
s = Solution()
s.doSomethingInScope([0, 1, 2])
In Python, everything is an object and every object is passed in reference . Therefore basically any changes you directly made on the passed object besides reassigning is always reflected on the object itself in real time. The key thing to note is the mutability of the object, ie whether the object is mutable pass its initial assignment.
For example, str
and int
objects are immutable. Note there are never any methods under str
and int
that changes the object directly:
s = 'foo' # str type
s.upper() # FOO
print(s)
# foo
Note how str.upper()
method doesn't change s
itself. in order to make s
into "FOO", you need to reassign s
:
s = s.upper()
print(s)
# FOO
However by reassigning the object ( obj = ...
) it changes the object reference, where id(s)
will now be different. So if a str
was passed like this:
def func(string):
string = string.upper()
func(s)
s
will remain unchanged because at the point of reassignment string = ...
, string
will no longer have the same object reference of s
.
However, with mutable objects, as long as you don't reassign, the object itself will take the changes:
l = list('abcde')
def func(lst, value):
lst.append(value)
# no reassignment
func(l, 'f')
print(l)
# ['a', 'b', 'c', 'd', 'e', 'f']
That is because the object reference ( id(l)
) remains the same within the function.
All that said, in your case, if you wanted to do something with the object but not mutate it, you want to either pass a copy of the object (which will have a different id
), or create a copy of the passed object in the local scope:
# pass a copy of the object:
def func(lst):
lst.append('x')
return lst
func(lst[:])
# OR, create a local object
def out_of_scope(lst):
temp_lst = lst[:]
temp_lst.append('x')
return temp_lst
In this particular case, [:]
returns a full slice
of the list
as a different object.
For a bit more information, here's a relevant read .
Python列表实际上是可变的,并通过引用传递
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.