Function attributes: a bug?

Roel Mathys Roel.Mathys at yucom.be
Sat Mar 29 03:10:31 EST 2003


Default arguments are evaluated once.  So if you call afterwards the 
function these arguments aren't re-evealuted again.
For mutable objects, like lists, dicts, you get the phenomenon you 
encountered.

Typically you should do:

	def f( default_arg = None ) :
		if default_arg is None :
			default_arg = []
		...

to circumvent this behaviour.


To make it work with the your functions, you should pass init to the 
nested functions:

	def make_list_accum( init = None ) :
		def accum( elem , init = init ) :
			if init is None :
				init = []
			accum.list = init
			accum.list.append( elem )
			return accum.list
		return accum

which does what you had in mind, I hope.

bye,
roel


Tj wrote:
> Hi,
> 
> I'm trying to make a closure using the following code.  It returns a
> function that can be used to keep adding stuff to a list.
> 
> def make_list_accum(init=[]):
>     def accum(elem):
>         accum.list.append(elem)
>         return accum.list
>     accum.list = init
>     return accum
> 
> But there's a bug -- if I generate a function using this, use it for a
> while to build up a list, then call make_list_accum() again, it will
> want to init itself with the other list by default, sharing it!  This
> is surprising behavior, and doesn't happen if I don't use this
> optional init form.
> 
> Any thoughts?
> 
> BTW, I want to send something like this to Paul Graham for his closure
> shootout.  Is this better than the normal version which uses objects?
> 
> Tj





More information about the Python-list mailing list