开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜