Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between mutation, rebinding, copying value, and assignment operator

#!/usr/bin/env python3.2

def f1(a, l=[]):
    l.append(a)
    return(l)

print(f1(1))
print(f1(1))
print(f1(1))

def f2(a, b=1):
    b = b + 1
    return(a+b)

print(f2(1))
print(f2(1))
print(f2(1))

In f1 the argument l has a default value assignment, and it is only evaluated once, so the three print output 1, 2, and 3. Why f2 doesn't do the similar?

Conclusion:

To make what I learned easier to navigate for future readers of this thread, I summarize as the following:

  • I found this nice tutorial on the topic.

  • I made some simple example programs to compare the difference between mutation, rebinding, copying value, and assignment operator.

like image 461
qazwsx Avatar asked Jan 31 '12 03:01

qazwsx


1 Answers

This is covered in detail in a relatively popular SO question, but I'll try to explain the issue in your particular context.


When your declare your function, the default parameters get evaluated at that moment. It does not refresh every time you call the function.

The reason why your functions behave differently is because you are treating them differently. In f1 you are mutating the object, while in f2 you are creating a new integer object and assigning it into b. You are not modifying b here, you are reassigning it. It is a different object now. In f1, you keep the same object around.

Consider an alternative function:

def f3(a, l= []):
   l = l + [a]
   return l

This behaves like f2 and doesn't keep appending to the default list. This is because it is creating a new l without ever modifying the object in the default parameter.


Common style in python is to assign the default parameter of None, then assign a new list. This gets around this whole ambiguity.

def f1(a, l = None):
   if l is None:
       l = []

   l.append(a)

   return l
like image 131
Donald Miner Avatar answered Sep 28 '22 08:09

Donald Miner