简体   繁体   中英

python function definition: function returning local to a global scope

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

print foo(10)
Result: [10]

print foo(20)
Result: [10, 20]

Why is this happening?

This line:

def foo(a, l=[]):

is creating a list at definition time .

That same list is being used every time the function is called.

Normally something like def foo(a, l="some string"): would work fine, but that's because string literals, integers and such are immutable and therefore it doesn't matter if every instance of the function accesses the same object in memory. Lists, on the other hand, are mutable.

You can get around this like so:

def foo(a, l=None):
    if l is None:
        l = []
    l.append(a)
    return l

This also creates a new list, but only upon execution of the function, in local scope. It won't reuse the same one.

When you give a default value to a function argument in python, it gets initialized only ONCE. That means even if you call your foo() a million times, you are appending to the SAME list.

print foo(10)  
print foo(20, [])

output:- [20]

this time you are sending another list reference so value will be inserted in another list reference.

If you do

def foo(a, l=[]):
    print id(l)
    ...
    ...
print foo(10)
print foo(20)

both time reference is same

140403877687808
[10]
140403877687808
[10, 20]

while in another case:-

    def foo(a, l=[]):
        print id(l)
        ...
        ...
    print foo(10)
    print foo(20, [])

reference changes:-

>>> 
140182233489920
[10]
140182233492512
[20]

It's because

   Default parameter values are always evaluated when, and only when, 
the “def” statement they belong to is executed.

    “def” is an executable statement in Python, and that default arguments are 
 evaluated in the “def” statement’s environment. If you execute “def” multiple times,
 it’ll create a new function object (with freshly calculated default values) each time.
 We’ll see examples of this below.

So here In your code, You are defining the list as default parameters. So it is evaluated only once when function is defined. Here come the reference of "def"

So only one object of list is created which is used multiple times whenever function is called and items get appended.

If you look the list identity then you will find function keeps returning the same object

>>> def foo(l=[]):
... l.append(1)
...return l    
>>> id(foo())
12516768
>>> id(foo())
12516768
>>> id(foo())
12516768

The way to achieve what you want to do is

def foo(a, l=None):
    if l is None:
        l = []
    #Do your stuff here with list l

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM