Something in the function tutorial confused me.

Steve Holden steve at holdenweb.com
Wed Aug 8 08:52:59 EDT 2007


greg wrote:
> Steve Holden wrote:
>> OK. The difference is that [] is a mutable value, while None is 
>> immutable.
> 
> No, it's not. It has nothing to do with mutability
> vs immutability.
> 
I beg to differ. That has everything to do with it.

> The difference is that in the first version the
> expression [] is evaluated only *once*, when the
> function is defined. Therefore there is just one
> list object getting re-used.
> 
In exactly the same way that with a default value of None just one None 
value is being re-used. The difference is that you have no way to nutate 
that value in place, whereas with a list object you can indeed do that.

> In the second version, the expression [] gets
> evaluated *each* time the function is called,
> creating a new list object each time.
> 
Correct.

>> When the function starts out with None as y's value any assignment to y 
>> causes it to reference a different value  (since None is immutable).
> 
> You're confused. Assigning to y simply causes it
> to reference whatever object is being assigned.
> This is always true, regardless of what y was
> referencing before.
> 
While it's correct that rebinding y will usually cause it to reference a 
different object, this need not be true of assignment. The augmented 
assignment operations do no necessarily rebind their left-hand operand - 
that depends on the implementation of the relevant method in whatever 
type is the subject of the augmented assignment.

An *assignment* to y therefore *usually* rebinds the name y to point to 
a different value. A *mutation* of the object *referenced* by y leaves y 
pointing to the same value. This is why appends to a default list 
argument are visible in later calls: because each call initializes y to 
reference the single object that was provided as the default value, 
which has been changed by previous calls.

> To see that the immutability of None has nothing
> to do with it, try the following version:
> 
> def f(x, y = []):
>    y = []
>    y.append(x)
>    print y
> 
> f(17)
> f(42)
> 
> Try to work out what it will do, then try it, and
> see if you understand why it does what it does.
> 
I know exactly what it will do without running it, thank you. Each call 
will return a single-valued list. It's hardly relevant, though since the 
value of the default argument isn't used anywhere in the function body. 
You are correct in stating that the [] construct always creates a new 
list. However, your explanation of why a list as a default argument 
retains mutations in further calls seems to me to omit some important 
details.

For some reason your reply got right up my nose, so I have had to 
restrain the impulse to be unpleasant. I'm left wondering if that's 
because of something in your reply (such as your assumption that your 
understanding of this situation is superior to mine) or because I got 
out of the wrong side of bed this morning. I'm currently giving you the 
benefit of the doubt, and going for another cup of coffee.

regards
  Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC/Ltd           http://www.holdenweb.com
Skype: holdenweb      http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------




More information about the Python-list mailing list