Consider the following cases:
Case 1:
def fun(arg):
arg += 1
my_var = 1
fun(my_var)
print(my_var)
>> 1
Case 2:
def fun(arg):
arg += [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3, 4]
Case 3:
def fun(arg):
arg = arg + [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3]
Case 4:
def fun(arg):
print(arg)
fun("Hi")
print(arg)
>> Hi
Traceback (most recent call last):
File "<string>", line 8, in <module>
NameError: name 'arg' is not defined
Case 4 demonstrates that the scope of the argument variable lies within the function. Case 1 and 3 support that as changes to the arg variable within the function are not reflected in the parameters globally.
But why does Case 2 happen at all? I noticed the same thing when I used append instead of the +=. Shouldn't the changes that happen to arg not have any effect on the variables the function was called with from a different scope?
Any help appreciated. Thanks in advance.
The answer is simple: Function arguments are local variables!
Some more observations:
= is the assignment operator and rebinds a variable. This will never mutate objects (ecxeption slice assignment).
+= is its own operator and is implemented as a mutation for mutable types. You can implement its behaviour for your own types by implementing the __iadd__ dunder method.
Hence, in general, a = a + b is not equivalent to a += b!
For lists, a += b corresponds to a.extend(b). a + b on the other hand, creates a new list object, and a = a + b rebinds variable a to that new object.
Case 2 is the only one where you use a mutating method on an instance. This affects the parameter passed.
The others do nothing or just reassign the argument. Assignment in python only affects the variable being assigned and not other variables that still refer to the previous instance.
Mandatory link to Ned Batchelder
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With