5 Replies - 768 Views - Last Post: 14 August 2010 - 07:25 PM Rate Topic: -----

#1 Motoma  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 797
  • Joined: 08-June 10

Python's Mutable Default Arguments

Posted 10 August 2010 - 03:55 PM

So I was reading through Rich Smith's pyREtic slides from Blackhat and came across the section of less-known bugs and flaws. The part that interested me the demonstration of mutable default arguments. The a slightly modified version of the example:

>>> def call_me(args_in = [])
SyntaxError: invalid syntax
>>> def call_me(args_in = []):
	args_in.append('foo')
	print args_in

	
>>> call_me(['a', 'b', 'c'])
['a', 'b', 'c', 'foo']
>>> call_me()
['foo']
>>> call_me()
['foo', 'foo']
>>> call_me(['a', 'b', 'c'])
['a', 'b', 'c', 'foo']
>>> call_me()
['foo', 'foo', 'foo']
>>> print args_in

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    print args_in
NameError: name 'args_in' is not defined



What is going on here? I don't quite understand what the purpose is, why this would be in the language, and how it is useful.

Any thoughts?

Is This A Good Question/Topic? 1
  • +

Replies To: Python's Mutable Default Arguments

#2 Motoma  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 797
  • Joined: 08-June 10

Re: Python's Mutable Default Arguments

Posted 10 August 2010 - 04:28 PM

So here's what I've got:

The empty list in call_me() is instantiated the moment call_me() is defined. In the case of the no arguments being passed, args_in starts as a reference to the empty list. The 'foo' is then appended to the empty list, which is never expunged from memory because of the reference in call_me()'s definition. Because the list object is mutable, and call_me()'s definition never changes, call_me() will now point to the non-empty list.

In the case of an argument being passed to call_me(), args_in will be a reference to the passed object, but only in the scope of that one call to call_me().

I'm still grappling with the implications of this. In situations where this is certainly unwanted, what I figure one should do is:

def call_me(args_in = None):
    if not args_in:
        args_in = []
    args_in.append('foo')
    print args_in



or

def call_me(args_in = None):
    scoped_args = []
    if args_in:
        scoped_args = args_in
    scoped_args.append('foo')
    print scoped_args



I'd love to hear others chime in with any thoughts about this.

Cheers,
Motoma
Was This Post Helpful? 0
  • +
  • -

#3 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Python's Mutable Default Arguments

Posted 10 August 2010 - 05:03 PM

This rather surprising behavior is consistent with Python. Effbot already has an explanation.
Was This Post Helpful? 2
  • +
  • -

#4 Motoma  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 797
  • Joined: 08-June 10

Re: Python's Mutable Default Arguments

Posted 10 August 2010 - 05:58 PM

View PostOler1s, on 10 August 2010 - 06:03 PM, said:

This rather surprising behavior is consistent with Python. Effbot already has an explanation.


Hey Oler1s, thank's for the very informative link.
Was This Post Helpful? 0
  • +
  • -

#5 Simown  Icon User is offline

  • Blue Sprat
  • member icon

Reputation: 319
  • View blog
  • Posts: 650
  • Joined: 20-May 10

Re: Python's Mutable Default Arguments

Posted 10 August 2010 - 06:06 PM

Thanks for bringing it up Motoma, I never thought to question "why include this behaviour?"

I knew I'd seen this before! Someone posted this link previously:

Force Default Arguments to be Evaluated Each Time

They use decorators to solve the "problem", although they also use the first example you suggested. It seems it is consistent with Python after all, from Oler1s link, just a bit annoying sometimes :P

This post has been edited by Simown: 10 August 2010 - 06:13 PM

Was This Post Helpful? 1
  • +
  • -

#6 atraub  Icon User is offline

  • Pythoneer
  • member icon

Reputation: 759
  • View blog
  • Posts: 2,010
  • Joined: 23-December 08

Re: Python's Mutable Default Arguments

Posted 14 August 2010 - 07:25 PM

It's interesting that you bring up this particular issue. I discussed it with Guido Van Rossum a few months ago. Here's what he had to say about it:

Quote

> This is a well-known gotcha in Python that most introductory materials
> ought to warn about. It is similar to having a list (or other mutable
> object) as a class variable. Unfortunately changing this behavior is
> impossible without breaking a large fraction of existing Python
> applications, so even at the Python 3 transition we decided to keep it
> and just keep users alert about the issue.
>
> You can find out more about it by Googling for keywords like "python
> mutable default"

This post has been edited by atraub: 14 August 2010 - 07:40 PM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1