First of all, here are two pieces of codes:
def foo(bar):
bar.append(42)
print(bar)
# >> [42]
answer_list = []
foo(answer_list)
print(answer_list)
# >> [42]
VS
def foo(bar):
bar = 'new value'
print (bar)
# >> 'new value'
answer_list = 'old value'
foo(answer_list)
print(answer_list)
# >> 'old value'
the results of above codes are different.
How should I answer this question?
Actually, variables are not objects; they cannot be denoted by other variables or referred to by objects. ‘Call-by-object’ or ‘call-by-object-reference’is correct. Why?
Python is object, just binding names to objects. There are two type objects: mutable object and immutable object.
· If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight,but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.
· If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.
my_list = [1, 2, 3]
my_list[0] = 4
print my_list # [4, 2, 3] <- The same list as changed
x = 6
x = x + 1 # The new x is another object
List - a mutable type
Let's try to modify the list that was passed to a method:
def try_to_change_list_contents(the_list):
print 'got', the_list
the_list.append('four')
print 'changed to', the_list
outer_list = ['one', 'two', 'three']
print 'before, outer_list =', outer_list
try_to_change_list_contents(outer_list)
print 'after, outer_list =', outer_list
Now let's see what happens when we try to change the reference that was passed in as a parameter:
def try_to_change_list_reference(the_list):
print 'got', the_list
the_list = ['and', 'we', 'can', 'not', 'lie']
print 'set to', the_list
outer_list = ['we', 'like', 'proper', 'English']
print 'before, outer_list =', outer_list
try_to_change_list_reference(outer_list)
print 'after, outer_list =', outer_list
String - an immutable type
It's immutable, so there's nothing we can do to change the contents of the string. Now, let's try to change the reference
def try_to_change_string_reference(the_string):
print 'got', the_string
the_string = 'In a kingdom by the sea'
print 'set to', the_string
outer_string = 'It was many and many a year ago'
print 'before, outer_string =', outer_string
try_to_change_string_reference(outer_string)
print 'after, outer_string =', outer_string
An object’s mutability is determined by its type; for instance, numbers, strings and tuples are immutable,while dictionaries and lists are mutable.
Question:
What if we need copy of one list? The copy module is the solution.
import copy
a = [1, 2, 3, 4, ['a', 'b']] #original object
b = a #assignment, reference to the original object
c = copy.copy(a) #shallow copy
d = copy.deepcopy(a) #deep copy
a.append(5) #modify object a
a[4].append('c') #modify the array object ['a', 'b'] in object a
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
Ref:
http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference
https://www.jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/