Default function arguments behaving badly

Discussion in 'Python' started by jonny.longrigg@gmail.com, Aug 24, 2005.

  1. Guest

    Hi

    I'm having some trouble with a function I've written in Python:

    def myFunction(l1,l2,result=[]):
    index=0
    for i in l1:
    result.append([])
    if type(i)==list:
    myFunction(i,l2,result[index])
    else:
    for j in l2:
    result[index].append(i*j)
    index+=1
    return result

    l1 and l2 are lists and the function multiplies every element of l1
    with every element of l2. l1 is (possibly) multi-dimensional, and the
    recursive bit is in there to cope with that. For example, if
    l1=[[1,2],[3,4]] and l2=[5,6] the result is
    [[[5,6],[10,12]],[[15,18],[20,40]]].

    The problem is that it works if I run it once, but then on repeated
    runs the value for 'result' doesn't seem to set itself to my default of
    [], but instead uses the state it was in last time the function was
    run.

    I've had a problem like this in the past and ended up rewriting the
    function as a class and using something like self.result, but I don't
    really like this solution as the code becomes considerabley more
    difficult to read (and I suspect less efficient). Also, I suppose I
    could feed in an empty array every time but that doesn't provide a very
    intuitive interface to the function.

    Does anyone know what is going on here? Is there an easy solution?

    Thanks for your help!
    , Aug 24, 2005
    #1
    1. Advertising

  2. rafi Guest

    wrote:
    > Hi


    hi

    > I'm having some trouble with a function I've written in Python:
    >
    > def myFunction(l1,l2,result=[]):
    > index=0
    > for i in l1:
    > result.append([])
    > if type(i)==list:
    > myFunction(i,l2,result[index])
    > else:
    > for j in l2:
    > result[index].append(i*j)
    > index+=1
    > return result


    > The problem is that it works if I run it once, but then on repeated
    > runs the value for 'result' doesn't seem to set itself to my default of
    > [], but instead uses the state it was in last time the function was
    > run.


    > Does anyone know what is going on here? Is there an easy solution?


    the list you provide as default parameter is evaluated once (at loading
    time of the function). so each time you call the function, it uses the
    same list that has been filled before... you do not have the problem
    with say and int or a string as they are non mutable objects. however
    lists are mutable objects so... modify your function as follow:

    def myFunction(l1,l2,result=None):
    if result is None:
    result = []

    hth

    --
    rafi

    "Imagination is more important than knowledge."
    (Albert Einstein)
    rafi, Aug 24, 2005
    #2
    1. Advertising

  3. Paul McNett Guest

    wrote:

    > I'm having some trouble with a function I've written in Python:


    > def myFunction(l1,l2,result=[]):

    [snipped rest of function and explanation of what it does]

    > Does anyone know what is going on here? Is there an easy solution?


    It shined out like a supernova. It has to do with mutability of certain
    Python objects (e.g. dicts and lists) and the fact that Python binds the
    default arguments only once. So, when your function is defined, python
    binds the name "result" to the value []. Then, your function runs the
    first time using that original binding. The second time, it still uses
    the original binding which, because lists are mutable, still contains
    the prior list. Etcetera.

    The solution is to never assign mutable objects to default arguments.
    Instead, assign to None, like:

    def myFunction(l1, l2, result=None):
    if result is None:
    result = []

    Others will certainly post links to the python docs that explain this.

    --
    Paul McNett
    http://paulmcnett.com
    Paul McNett, Aug 24, 2005
    #3
  4. Guest

    That works perfectly - Thanks! I'm always getting tripped up by the
    mutability of lists, I should really learn to look out for it more...
    , Aug 24, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Parrot

    Tables Behaving Badly

    Parrot, Jul 19, 2005, in forum: HTML
    Replies:
    12
    Views:
    762
    Jonathan N. Little
    Jul 20, 2005
  2. Ajax Chelsea
    Replies:
    1
    Views:
    432
    Ron Natalie
    Dec 2, 2003
  3. Edward Diener
    Replies:
    14
    Views:
    4,939
    Josiah Carlson
    Apr 6, 2004
  4. tutmann
    Replies:
    4
    Views:
    436
  5. jmborr
    Replies:
    1
    Views:
    411
    Stargaming
    Nov 3, 2007
Loading...

Share This Page