why are these not the same?

Duncan Booth duncan.booth at invalid.invalid
Thu Jan 20 05:06:01 EST 2005


Lowell Kirsh wrote:

> On a webpage (see link below) I read that the following 2 forms are not 
> the same and that the second should be avoided. They look the same to 
> me. What's the difference?
> 
> Lowell
> 
> ----
> 
> def functionF(argString="abc", argList = None):
>          if argList is None: argList = []
>          ...
> 
> def functionF(argString="abc", argList=None):
>          argList = argList or []
>          ...
> 
> http://www.ferg.org/projects/python_gotchas.html (number 5)

If functionF mutates its argument then these two will give different and 
possibly unexpected results. I suspect this is what they are hinting at:

>>> def f1(s="abc", l=None):
	if l is None: l = []
	l.append(s)
	return '*'.join(l)

>>> def f2(s="abc", l=None):
	l = l or []
	l.append(s)
	return '*'.join(l)

>>> f1('foo', ['bar'])
'bar*foo'
>>> f2('foo', ['bar'])
'bar*foo'
>>> f1('foo', [])
'foo'
>>> f2('foo', [])
'foo'

So far the functions appear to operate identically. But:

>>> myList = []
>>> f1('foo', myList)
'foo'
>>> myList
['foo']
>>> myList = []
>>> f2('foo', myList)
'foo'
>>> myList
[]

It looks as though f1 mutates its argument but f2 doesn't, until you try:

>>> f2('foo', myList)
'bar*foo'
>>> myList
['bar', 'foo']
>>> 
>>> 

So f2 mutates a non-empty list but leaves an empty list unchanged which is 
probably not what you intend and certainly confusing.



More information about the Python-list mailing list