In Python, it's possible to alter some types of objects within a function without having to return anything. For some objects, this is not the case.
For instance, if we pass a dictionary to a function and alter it within the function, the original dictionary will be altered:
def add_key(d, key):
d[key] = True
d = {}
print d
# {}
add_key(d, 1)
print d
# {1: True}
In contrast, we can't alter an integer like this:
def increment_int(i):
i += 1
i = 1
print i
# 1
increment_int(i)
print i
# still 1!
At first I thought that maybe the rule is simply that immutable objects cannot be altered within a function in this way. A similar example does not work with strings:
def append_string(s1, s2):
s1 += s2
s = "hello"
print s
# "hello"
append_string(s, " world")
print s
# "hello", not "hello world" :(
I'm confused though, because it seems that certain operations applied to a mutable object within a function will be visible afterwards, while others wont. E.g. appending an item to a list does work:
def append_list(l, val):
l.append(val)
l = []
print l
# []
append_list(l, 1)
print l
# [1]
while swapping the names of two lists doesn't:
def swap_lists(l1, l2):
l1, l2 = l2, l1
l1 = [1]
l2 = [2]
print l1, l2
# [1] [2]
swap_lists(l1, l2)
print l1, l2
# still [1] [2], even though lists are mutable!
Yet another example, with seemingly weird and unexpected behaviour:
def swap_then_append(l1, l2):
l1, l2 = l2, l1
l1.append(1)
l2.append(2)
l1 = []
l2 = []
print l1, l2
# [] []
swap_then_append(l1, l2)
print l1, l2
# [2] [1]
Can someone explain what is happening here?
Edit: a possible duplicate of this question has been identified; the answers there partially explain to me what is going on, I still don't get why, for instance, the function swap_lists
above doesn't actually swap the lists. And now that I am thinking about it further, I still don't actually understand why increment_int
and append_string
above don't do what I initially expected, other than that it has something to do with the immutability of integers and strings.