Re: Modifying the default argument of function
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
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
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
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
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
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