Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #64442 > unrolled thread

Modifying the default argument of function

Started byMû <mu--@melix.net>
First post2014-01-21 20:11 +0100
Last post2014-01-21 11:20 -0800
Articles 7 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Modifying the default argument of function Mû <mu--@melix.net> - 2014-01-21 20:11 +0100
    Re: Modifying the default argument of function Chris Angelico <rosuav@gmail.com> - 2014-01-22 06:19 +1100
      Re: Modifying the default argument of function Mû <mu--@melix.net> - 2014-01-21 20:36 +0100
        Re: Modifying the default argument of function Chris Angelico <rosuav@gmail.com> - 2014-01-22 06:46 +1100
          Re: Modifying the default argument of function Asaf Las <roegltd@gmail.com> - 2014-01-21 16:30 -0800
    Re: Modifying the default argument of function Steve Jones <steve@secretvolcanobase.org> - 2014-01-21 19:19 +0000
    Re: Modifying the default argument of function emile <emile@fenx.com> - 2014-01-21 11:20 -0800

#64442 — Modifying the default argument of function

FromMû <mu--@melix.net>
Date2014-01-21 20:11 +0100
SubjectModifying the default argument of function
Message-ID<52dec646$0$2934$426a74cc@news.free.fr>
Hi everybody,

A friend of mine asked me a question about the following code:

[code]
def f(x=[2,3]):
     x.append(1)
     return x

print(f())
print(f())
print(f())
[/code]

The results are [2, 3, 1], [2, 3, 1, 1] and [2, 3, 1, 1, 1].

The function acts as if there were a global variable x, but the call of 
x results in an error (undefined variable). I don't understand why the 
successive calls of f() don't return the same value: indeed, I thought 
that [2,3] was the default argument of the function f, thus I expected 
the three calls of f() to be exactly equivalent.

I'm don't know much about python, does anybody have a simple explanation 
please?

-- 
Mû

---
Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
http://www.avast.com

[toc] | [next] | [standalone]


#64444

FromChris Angelico <rosuav@gmail.com>
Date2014-01-22 06:19 +1100
Message-ID<mailman.5813.1390331956.18130.python-list@python.org>
In reply to#64442
On Wed, Jan 22, 2014 at 6:11 AM, Mû <mu--@melix.net> wrote:
> The function acts as if there were a global variable x, but the call of x
> results in an error (undefined variable). I don't understand why the
> successive calls of f() don't return the same value: indeed, I thought that
> [2,3] was the default argument of the function f, thus I expected the three
> calls of f() to be exactly equivalent.

In a sense, there is. The default for the argument is simply an object
like any other, and it's stored in one place.

For cases where you want a mutable default that is "reset" every time,
the most common idiom is this:

def f(x=None):
    if x is None: x=[2,3]
    x.append(1)
    return x

That will create a new list every time, with the same initial contents.

ChrisA

[toc] | [prev] | [next] | [standalone]


#64448

FromMû <mu--@melix.net>
Date2014-01-21 20:36 +0100
Message-ID<52decc31$0$2244$426a74cc@news.free.fr>
In reply to#64444
Le 21/01/2014 20:19, Chris Angelico a écrit :
> On Wed, Jan 22, 2014 at 6:11 AM, Mû <mu--@melix.net> wrote:
>> The function acts as if there were a global variable x, but the call of x
>> results in an error (undefined variable). I don't understand why the
>> successive calls of f() don't return the same value: indeed, I thought that
>> [2,3] was the default argument of the function f, thus I expected the three
>> calls of f() to be exactly equivalent.
>
> In a sense, there is. The default for the argument is simply an object
> like any other, and it's stored in one place.
>
> For cases where you want a mutable default that is "reset" every time,
> the most common idiom is this:
>
> def f(x=None):
>      if x is None: x=[2,3]
>      x.append(1)
>      return x
>
> That will create a new list every time, with the same initial contents.
>
> ChrisA
>

Thank you, thanks everybody,

These were clear and quick answers to my problem. I did not think of 
this possibility: the default argument is created once, but accessible 
only by the function, therefore is not a global variable, whereas it 
looks like if it were at first glance.

-- 
Mû


---
Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
http://www.avast.com

[toc] | [prev] | [next] | [standalone]


#64449

FromChris Angelico <rosuav@gmail.com>
Date2014-01-22 06:46 +1100
Message-ID<mailman.5816.1390333586.18130.python-list@python.org>
In reply to#64448
On Wed, Jan 22, 2014 at 6:36 AM, Mû <mu--@melix.net> wrote:
> These were clear and quick answers to my problem. I did not think of this
> possibility: the default argument is created once, but accessible only by
> the function, therefore is not a global variable, whereas it looks like if
> it were at first glance.

You can actually poke at the function a bit and see what's happening.
Try this in the interactive interpreter:

>>> def f(x=[2,3]):
    x.append(1)
    return x

>>> f()
[2, 3, 1]
>>> f()
[2, 3, 1, 1]
>>> f.__defaults__
([2, 3, 1, 1],)

The __defaults__ attribute of a function is a tuple of its parameter
defaults. You can easily see there that the list has changed as you
changed it in the function. You could check it with id() or is, too:

>>> id(f.__defaults__[0])
24529576
>>> id(f())
24529576
>>> f() is f.__defaults__[0]
True

ChrisA

[toc] | [prev] | [next] | [standalone]


#64468

FromAsaf Las <roegltd@gmail.com>
Date2014-01-21 16:30 -0800
Message-ID<5e78b144-5e3d-48c2-adb1-df64878b8bf2@googlegroups.com>
In reply to#64449
On Tuesday, January 21, 2014 9:46:16 PM UTC+2, Chris Angelico wrote:
> On Wed, Jan 22, 2014 at 6:36 AM, Mû <mu--@melix.net> wrote:
> > These were clear and quick answers to my problem. I did not think of this
> > possibility: the default argument is created once, but accessible only by
> > the function, therefore is not a global variable, whereas it looks like if
> > it were at first glance.
> You can actually poke at the function a bit and see what's happening.
> Try this in the interactive interpreter:
> >>> def f(x=[2,3]):
>     x.append(1)
>     return x
> >>> f()
> [2, 3, 1]
> >>> f()
> [2, 3, 1, 1]
> >>> f.__defaults__
> ([2, 3, 1, 1],)
> 
> The __defaults__ attribute of a function is a tuple of its parameter
> defaults. You can easily see there that the list has changed as you
> changed it in the function. You could check it with id() or is, too:
> >>> id(f.__defaults__[0])
> 24529576
> >>> id(f())
> 24529576
> >>> f() is f.__defaults__[0]
> True
> ChrisA

that reminds me C's static :-)

def func(y, x = [1]):
    if y != 1 :
        func.__defaults__[0][0] = y
    print(func.__defaults__[0])

func(0)
func(2)
func(1)

[0]
[2]
[2]

p.s. Mu, thanks for question!

[toc] | [prev] | [next] | [standalone]


#64445

FromSteve Jones <steve@secretvolcanobase.org>
Date2014-01-21 19:19 +0000
Message-ID<20140121191953.6c8dae28@steves-laptop>
In reply to#64442
On Tue, 21 Jan 2014 20:11:02 +0100
Mû <mu--@melix.net> wrote:

> Hi everybody,
> 
> A friend of mine asked me a question about the following code:
> 
> [code]
> def f(x=[2,3]):
>      x.append(1)
>      return x
> 
> print(f())
> print(f())
> print(f())
> [/code]
> 
> The results are [2, 3, 1], [2, 3, 1, 1] and [2, 3, 1, 1, 1].
> 
> The function acts as if there were a global variable x, but the call of 
> x results in an error (undefined variable). I don't understand why the 
> successive calls of f() don't return the same value: indeed, I thought 
> that [2,3] was the default argument of the function f, thus I expected 
> the three calls of f() to be exactly equivalent.
> 
> I'm don't know much about python, does anybody have a simple explanation 
> please?

x is assigned to the list [2, 3] at the time the function is created not when the function is called, meaning that there's only ever 1 list created. When you call x.append this list is modified and the next time the function is called x still refers to this modified list.

[toc] | [prev] | [next] | [standalone]


#64446

Fromemile <emile@fenx.com>
Date2014-01-21 11:20 -0800
Message-ID<mailman.5814.1390332031.18130.python-list@python.org>
In reply to#64442
Function defs with mutable arguments hold a reference to the mutable 
container such that all invocations access the same changeable container.

To get separate mutable default arguments, use:

def f(x=None):
   if x is None: x=[2,3]

Emile

On 01/21/2014 11:11 AM, Mû wrote:
> Hi everybody,
>
> A friend of mine asked me a question about the following code:
>
> [code]
> def f(x=[2,3]):
>      x.append(1)
>      return x
>
> print(f())
> print(f())
> print(f())
> [/code]
>
> The results are [2, 3, 1], [2, 3, 1, 1] and [2, 3, 1, 1, 1].
>
> The function acts as if there were a global variable x, but the call of
> x results in an error (undefined variable). I don't understand why the
> successive calls of f() don't return the same value: indeed, I thought
> that [2,3] was the default argument of the function f, thus I expected
> the three calls of f() to be exactly equivalent.
>
> I'm don't know much about python, does anybody have a simple explanation
> please?
>

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web