anything like C++ references?

Stephen Horne intentionally at blank.co.uk
Sun Jul 13 13:51:47 EDT 2003


On 13 Jul 2003 12:19:08 -0400, aahz at pythoncraft.com (Aahz) wrote:

>Whether one can mutate a specific object is simply an
>attribute of that object, rather than requiring a different syntax.
>Trying to focus on the mutable/immutable distinction is what causes the
>mental blowup -- keep your eye on the objects and bindings and you're
>fine.

That's exactly it - you have to focus on whether an object is mutable
or immutable for that exact reason.

While I admit I'm not sure, I believe that in early versions of Python
immutable values literally were copied. Mutable types were made
mutable because of efficiency concerns about copying overheads that
would occur otherwise. If an object is large enough that it is
worthwhile modifying items within it in-place then it tends to be
worthwhile trying to avoid copying overheads, even though these two
aspects of 'mutability' are actually quite distinct in principle.

Actually, I'm convinced there are some flaws in Guidos own logic
*unless* this is the case. Take for instance this...

http://www.python.org/search/hypermail/python-1992/0292.html

"""
<A> They serve different purposes. Lists can get quite long, they are
generally built incrementally, and therefore have to be mutable.
Tuples on the other hand are generally short and created at once.


<Q> Then why can't tuples be mutable and serve both purposes?


<A> Imagine a graphics class that stores coordinates of graphical
objects as tuples. It may also store rectangles as a tuple of points,
etc. If tuples were mutable, the class would have to store copies of
all points and rectangles it receives, since otherwise a caller who
creates a point variable, passes its value to the graphics class, and
later changes the point for its own use (e.g., to create another
graphical object with slightly different coordinates) might violate
the internal consistency of the graphics class. Note that most
callers woouldn't modify the points, but the graphics class has no way
to tell, so it has to make the copies anyway. (And now imaging the
software is actually layered in such a way that coordinates are passed
down several levels deep...)
"""

So what?

As things are, the points could be stored using a list of tuples, with
each tuple representing a point. When you store a new point in the
list, you don't immediately make a copy (so if the supplier of the
point immediately discards it, no copying is needed at all except for
pointers) so it is efficient - yet you are still guarenteed that
external processing will not mutate the value you hold in your list.

Fine.

But that can be achieved equally well by applying a copy-on-write
system to *all* types, without a distinction between mutable and
immutable for this purpose.

Equally, you could use the same rationale for storing items which
Python classes as mutable instead of these point tuples. If you have
an object which stores class instances or dictionaries or lists for
you, you need to store copies as - just as Guido recognised for the
tuple case - your object doesn't know for sure what the caller is
going to do with those objects after passing them in as parameters.

This makes no sense to me *unless* there were other reasons for the
mutable/immutable distinction. If lists had copy-on-write semantics,
they could still be mutable (ie support in-place modification) yet
there would be no need to make early copies. Tuples would be redundant
as their only distinctive feature would be their lack of support for
in-place modifications. It only makes sense if the copy-on-write for
immutable values hadn't been implemented when the distinction was
created - if immutables did not use references, but were always copied
immediately on assignment - so that the referencing mechanism need
never worry about copy-on-write at all.


But it is worse than just being an arbitrary and pointless
distinction...

Back when PEP238 was being 'debated', a major argument in favor of the
change was that there is no legitimate case where a function would
need to either do 'true' division or integer division depending on the
argument type. The type of division needed depends on the purpose of
the function, and behaviour shouldn't change just because someone
passes an integer into a function that expects a real or visa versa.

Apply the same logic to mutable and immutable types.

Tell me one case where it is sensible for a function to behave such
that whether the caller sees a change in a variable it passed as its
argument should depend on the type.

Tell me one case where an object storing values should care about
callers mutating values it holds *only* for certain types.

I doubt you can.

This is an arbitrary distinction created for historic reasons that
have long since vanished (apart, of course, from backward
compatibility and psychological inertia), given that copy-on-write is
implemented for immutable objects anyway. And the fact that immutable
values do an excellent job of implementing the common semantics of
most imperitive languages (i.e. assignment sets the LHS to something
that can be treated as a distinct copy) whereas mutable types behave
in a fundamentally different way is quite simply a wart -
inconsistent, confusing and error-prone behaviour.





More information about the Python-list mailing list