inhibit sharing default arg b/w successive calls
Python Tutorial -
Important warning: The default value is evaluated only once ... If you don’t want the default to be shared between subsequent calls, you can write the function like this instead:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
I still was expecting:
print f(1) # [1]
print f(2) # [1,2]
print f(3) # [1,2,3]
I reason:
The default value (L=None
) was executed for f(1)
which helped L point to a new empty list in the fn body. However on successive calls, L=None
was 开发者_运维知识库not executed; so L still points to the list which already has 1 in it now, and subsequent calls are simply appending more elements to it thereby sharing L
.
Where am I thinking incorrectly?
UPDATE
def f(a, L=[]):
L.append(a)
return L
Does L here point to an empty list created in heap or stack?
L
is the name of an argument, but it is also a local variable. Rebinding it rebinds the local variable, but does not change the default argument.
UPDATE EDIT:
Python doesn't have "heap" and "stack" in the same manner as C; all it has are objects, and references to those objects. Your function call returns a reference to the same list that was created as the default value for the L
argument of the f
function, and any operation that mutates it will mutate the value of the default argument.
The default value is evaluated only once
means that if you do def foo(a, b=len([1,2,3]))
b will be set to 3 and it will not make any function call to len
if you call foo.
The =
operator assigns an object to a name. It doesn't change the previous object.
If you run the functions below, it will help you to see how it works.
def f(a, L=[]):
print("id default: ", id(L))
L.append(a)
print("id used: ", id(L)
return L
Notice 1 object address, we are using only the default list object and we are changing it.
def f(a, L=[]):
print("id default: ", id(L))
if L == []:
L = []
L.append(a)
print("id used: ", id(L))
return L
Notice 2 different object addresses, when you assign L=[] again in the function, you are using a different list object and not the default list object, and that is why the default list object doesn't change.
def f(a, L=None):
print("id default", id(L))
if L is None:
L = []
L.append(a)
print("id used: ", id(L))
return L
This function is basically the same as the one above it, same idea, but it uses a None object instead of an empty list object.
精彩评论