Re: Modifying the default argument of function

2014-01-21 Thread Steve Jones
On Tue, 21 Jan 2014 20:11:02 +0100
Mû m...@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.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Modifying the default argument of function

2014-01-21 Thread emile
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?




--
https://mail.python.org/mailman/listinfo/python-list


Re: Modifying the default argument of function

2014-01-21 Thread Chris Angelico
On Wed, Jan 22, 2014 at 6:11 AM, Mû m...@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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Modifying the default argument of function

2014-01-21 Thread

Le 21/01/2014 20:19, Chris Angelico a écrit :

On Wed, Jan 22, 2014 at 6:11 AM, Mû m...@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

--
https://mail.python.org/mailman/listinfo/python-list


Re: Modifying the default argument of function

2014-01-21 Thread Chris Angelico
On Wed, Jan 22, 2014 at 6:36 AM, Mû m...@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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Modifying the default argument of function

2014-01-21 Thread Asaf Las
On Tuesday, January 21, 2014 9:46:16 PM UTC+2, Chris Angelico wrote:
 On Wed, Jan 22, 2014 at 6:36 AM, Mû m...@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!
-- 
https://mail.python.org/mailman/listinfo/python-list