Optional parameter object re-used when instantiating multiple objects

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Nov 16 05:05:20 EST 2008


On Sun, 16 Nov 2008 07:05:51 +0000, Arnaud Delobelle wrote:

> Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:
> 
>> On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
>>
>>> Hello All,
>>> 
>>> Why is python designed so that b and c (according to code below)
>>> actually share the same list object? It seems more natural to me that
>>> each object would be created with a new list object in the points
>>> variable.
>>
>> That's not natural *at all*. You're initialising the argument "points"
>> with the same list every time. If you wanted it to have a different
>> list each time, you should have said so. Don't blame the language for
>> doing exactly what you told it to do.
> 
> Come on.  The fact that this questions comes up so often (twice in 24h)
> is proof that this is a surprising behaviour.

Of course it's surprising. People make an assumption based on other 
languages. But there is nothing "natural" about that assumption. It may 
be common, but that doesn't mean it's the only way to think about it.

If you check the archives of this newsgroup, you will see that some time 
not very long ago I made the suggestion that perhaps Python should raise 
a warning when it creates a function with an obviously mutable default 
argument. In practice, that would mean checking for three special cases: 
[], {} and set(). So I'm sympathetic towards the surprise people feel, 
but I don't agree that it is natural. "Natural" is a thought-stopper. 
It's meant to imply that any other alternative is unnatural, crazy, 
stupid, perverted, or whatever other alternative to natural you prefer, 
therefore stop all disagreement.



> I do think it is the
> correct one but it is very natural to assume that when you write
> 
>     def foo(bar=[]):
>          bar.append(6)
>          ...
> 
> you are describing what happens when you _call_ foo, i.e.:
> 
>     1. if bar is not provided, make it equal to [] 
>     2. Append 6 to bar
>     3. ...


Which is *exactly* what happens -- except of course once you append six 
to the list [], it now looks like [6].

Why assume that "make it equal to []" implies a different list every 
time, rather than that it is a specific list that happens to start off as 
[]? Why isn't it equally "natural" to assume that it's the same list each 
time, and it starts off as [] but need not stay that way?


-- 
Steven



More information about the Python-list mailing list