FAQ
hello,

i have an unexpected behaviour that i didn't understand, can someone explain
this to me ?
def doit(s, stack = []):
if s == '':
return stack

stack.append(s[:1])
return doit(s[1:], stack)
doit('this')
['t', 'h', 'i', 's']
doit('this')
['t', 'h', 'i', 's', 't', 'h', 'i', 's']
doit('this')
['t', 'h', 'i', 's', 't', 'h', 'i', 's', 't', 'h', 'i', 's']

and so on ... i would expect it to stuck to
doit('this')
['t', 'h', 'i', 's']

why does this 'stack' remind of previous call ?

thanks.

Search Discussions

  • Ulrich Petri at Aug 31, 2003 at 11:24 am
    "shagshag13" <shagshag13 at yahooPLUSDESPAM.fr> schrieb im Newsbeitrag
    news:3f51ce6e$0$26843$626a54ce at news.free.fr...
    hello,

    i have an unexpected behaviour that i didn't understand, can someone explain
    this to me ?
    def doit(s, stack = []):
    if s == '':
    return stack

    stack.append(s[:1])
    return doit(s[1:], stack)
    doit('this')
    ['t', 'h', 'i', 's']
    doit('this')
    ['t', 'h', 'i', 's', 't', 'h', 'i', 's']
    doit('this')
    ['t', 'h', 'i', 's', 't', 'h', 'i', 's', 't', 'h', 'i', 's']

    and so on ... i would expect it to stuck to
    doit('this')
    ['t', 'h', 'i', 's']

    why does this 'stack' remind of previous call ?
    Try this:
    >>>
    def doit(s, stack=None):
    if stack == None:
    stack=[]
    if s == '':
    return stack

    stack.append(s[:1])
    return doit(s[1:], stack)

    The problem is the default value auf stack.

    IIRC Default values are not created each time the function called but rather
    only the first time (am i correct here?). And since a list is mutable it
    "rememberes" the previous value.

    Ciao Ulrich
  • Alex Martelli at Aug 31, 2003 at 1:19 pm
    Ulrich Petri wrote:
    ...
    IIRC Default values are not created each time the function called but
    rather only the first time (am i correct here?). And since a list is
    Almost, but not quite: they're created when the function is DEFINED,
    *not* the first time it's called. For example:
    x=3
    def f(d=x*'u'): return d
    ...
    x=8
    print f()
    uuu

    The fact that global variable x is worth 8 by the time f is first called
    is irrelevant: what governs is that x was worth 3 when the def statement
    was executed -- THAT instant is the one in which the default value of d
    is termined and stored in the function-object f... at creation time for the
    function-object f, i.e. execution time for the def statement.
    mutable it "rememberes" the previous value.
    Yes, this is correct: if the default value of an argument is mutable, it
    "remembers" whatever mutations you choose to perform on it.


    Alex
  • Mel Wilson at Aug 31, 2003 at 2:32 pm
    In article <bislss$ckt13$1 at ID-67890.news.uni-berlin.de>,
    "Ulrich Petri" wrote:
    IIRC Default values are not created each time the function called but rather
    only the first time (am i correct here?). And since a list is mutable it
    "rememberes" the previous value.
    Default values are created when the 'def' statement is
    executed, for example:


    def f1 (t, usual=[]):
    usual.append (t)
    print 'F1:', usual

    for x in [1, 2, 3, 4, 5]:
    def f2 (t, usual=[]):
    usual.append (t)
    print 'F2:', usual

    f1 (x)
    f2 (x)


    Results in


    F1: [1]
    F2: [1]
    F1: [1, 2]
    F2: [2]
    F1: [1, 2, 3]
    F2: [3]
    F1: [1, 2, 3, 4]
    F2: [4]
    F1: [1, 2, 3, 4, 5]
    F2: [5]


    Regards. Mel.
  • Michael Peuser at Aug 31, 2003 at 5:11 pm
    "Mel Wilson" <mwilson at the-wire.com> schrieb im Newsbeitrag
    news:obgU/ks/KbsM089yn at the-wire.com...
    In article <bislss$ckt13$1 at ID-67890.news.uni-berlin.de>,
    "Ulrich Petri" wrote:
    IIRC Default values are not created each time the function called but
    rather
    only the first time (am i correct here?). And since a list is mutable it
    "rememberes" the previous value.
    Default values are created when the 'def' statement is
    executed,
    This seems to be generally a somewhat underestimated issue...

    See this example:
    while c:
    b=Button(...)
    b.config(command=lambda x=b: doSomething(x))

    This would not work otherwise...


    Kindly
    Michael P
  • Michael Peuser at Aug 31, 2003 at 1:58 pm
    "shagshag13" <shagshag13 at yahooPLUSDESPAM.fr> schrieb im Newsbeitrag
    news:3f51ce6e$0$26843$626a54ce at news.free.fr...
    hello,

    i have an unexpected behaviour that i didn't understand, can someone explain
    this to me ?

    This is a feature, nor a bug ;-)
    As Python has no 'static' local variables, you can use this trickily to
    emulate them. Note however that the preset value has to be mutable, {} e.g.

    Kindly
    Michael P
  • Caleb Land at Aug 31, 2003 at 8:05 pm
    "shagshag13" <shagshag13 at yahooPLUSDESPAM.fr> wrote in message news:<3f51ce6e$0$26843$626a54ce at news.free.fr>...
    hello,

    i have an unexpected behaviour that i didn't understand, can someone explain
    this to me ?
    def doit(s, stack = []):
    if s == '':
    return stack

    stack.append(s[:1])
    return doit(s[1:], stack)
    doit('this')
    ['t', 'h', 'i', 's']
    doit('this')
    ['t', 'h', 'i', 's', 't', 'h', 'i', 's']
    doit('this')
    ['t', 'h', 'i', 's', 't', 'h', 'i', 's', 't', 'h', 'i', 's']

    and so on ... i would expect it to stuck to
    doit('this')
    ['t', 'h', 'i', 's']

    why does this 'stack' remind of previous call ?
    The problem is your function declaration:
    def doit(s, stack = []):

    That empty list is evaluated only once, so each call to doit without a
    stack argument uses the same list.

    You should change that to:

    def doit(s, stack=None):
    if s == '':
    return stack

    if stack is None:
    stack = [] # A new empty list is created each time

    stack.append(s[:1])
    return doit(s[1:], stack)

    -Caleb Land

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedAug 31, '03 at 10:36a
activeAug 31, '03 at 8:05p
posts7
users6
websitepython.org

People

Translate

site design / logo © 2022 Grokbase