[Edu-sig] Pass by Reference
John Zelle
john.zelle at wartburg.edu
Wed May 21 05:55:24 CEST 2008
Hi Warren,
Some interesting thoughts. You have given me something of a new insight.
(So call this a post on a related topic :-)
On Tue, 2008-05-20 at 18:35 -0700, Warren Sande wrote:
> I would argue that from a "functional" point of view (black box, the
> way it behaves), Python does behave like call-by-reference, for
> mutable types.
>
> In another language, if I use call-by-reference, and the function
> modifies the variable, the caller's variable changes. That's the same
> behavior I get in Python with mutable types (just as in John Posner's
> example).
OK. Again, this is not about parameter passing. To demonstrate, let's
take a language that has both call-by-reference and call-by-value,
Pascal springs to mind. If you send a linked list (most probably a
pointer to a header node) by value in Pascal and you change the
structure of the linked list, guess what, the change appears back in the
caller. The same thing happens if you use Pascal's pass by reference
mechanism. This example is not a test of what kind of parameter passing
you do. It is a test of whether the variable you pass holds a reference
or actually stores the object. Of course all Python variables hold
references and are therefore analogous (in this respect) to Pascal
pointers.
> I understand that it is not truly call-by-reference. But from the
> outside, that's what it looks like, for mutable types. For immutable
> types it looks like call-by-value, since changing it in the function
> does not change the caller's "copy"
I simply don't understand this comment. You can't change an immutable
object in the caller or the callee. That's what makes the object
immutable. What you can do is change what object a variable refers to
(by assignment) and that change has no effect in the callee regardless
of whether the type of the object (originally) being referred to is
mutable or not.
>
> I definitely agree that Python is the best choice for a first
> language. But there is this one inconsistency (or maybe call it a
> duality) of mutable vs immutable types, that I think can be a bit
> confusing.
>
> Putting aside the "pass-by-X" question, a beginner asks:
>
> "If I do A = (something) then B = A then I change A, does B
> also change?"
The answer to this question is "yes" always and everywhere in Python. If
A refers to a mutable object, then any changes through A will be visible
to B. If A's object is not mutable, then you can't change it, period. So
if you can make a change to A's object, it is mutable and B's object
changes as well (since they are the same object).
If you mean does reassigning A have any effect on B, then the answer is
"no" always and everywhere in Python. Setting A = C will change A's
reference and have no effect whatsoever on B, it makes no difference
whether A's original object was mutable or not.
> And the answer, again, is "It depends." For mutable types, yes, for
> immutable types, no. And that's a sticky thing to get into for a
> beginner who is just learning what variables (names) are about.
No, it does not depend on whether the object is mutable. It depends on
whether you are changing the object or reassigning the variable. The
question is not whether A refers to a mutable object, but rather, what
does the student mean by "change A." Does he/she mean assign A to be a
different object or apply an operation that changes the state of A's
object. When posed that way, both answers seem fairly obvious.
I think you are on to something here, namely that some confusion
actually stems from the overloaded meaning of "Change A." That can mean
either change what A refers to or change the state of the object that A
refers to. Perhaps as teachers we need to be more careful about using
phrases like "reassign A" and "change A's object" vs. "change A." No
doubt, this is what leads to your (apparent) mutable/immutable
dichotomy, since reassignment is the one and only way to "change A" if A
is a reference to an immutable object.
> >>> a = 5
> >>> b = a
> >>> a
> 5
> >>> b
> 5
> >>> a = 7
> >>> a
> 7
> >>> b
> 5
>
> >>> a = [8]
> >>> b = a
> >>> a
> [8]
> >>> b
> [8]
> >>> a.append(9)
> >>> a
> [8, 9]
> >>> b
> [8, 9]
>
> I know that in the first case, you are not really "changing" a, you
> are attaching the name 'a' to a new object (7, instead of 5). But
> that's not what it looks like from the outside. It looks like you are
> changing a, and b is not changing. In the second case, you are
> changing a, and b is changing.
I really like your example, because it makes my point that this
discussion is not about parameter passing at all, but rather about
memory models. But I don't understand what you mean "that is not what it
looks like from the outside." In one case you reassign a and in the
other case you don't. They _look_ like _very_different_ things (a = 8,
vs. a.append(9)). Therefore one should probably expect they have very
different effects, which they do. If you just draw the picture of what
assignment does (using arrows for references), these examples are
crystal clear. I don't think it should be confusing for newbies. It's
probably more confusing for us oldbies. Or perhaps, as suggested above
we sow confusion ourselves by generically saying both of these "change
a".
> I'm not saying the memory model is inconsistent, just that it can
> appear that way to a beginner. And I think that's true whether they
> have had exposure to another language or not.
>
If you tell your students that assignment causes the variable to be
attached to a different object (my sticky note analogy), then it should
be pretty obvious that performing an assignment does not affect another
variable (you're just removing one label from the object). If you tell
them that assignment of one variable to another gives them another name
for the same object (puts another note on the same object), then they
should expect both names to see the any changes to the object (ala
Kirby's leash example).
I can see room for confusion if you are already used to a language that
routinely makes copies of complex objects via assignment and somehow
expect Python to be making copies of those objects. But if Python is a
student's first language, why on earth would one expect that? It's not a
more intuitive model, just a different one. When I teach C/C++ to my
Python-aware students, the first hurdle is to grasp that variables
represent locations and that assignment copies values not references.
They find that model a bit confusing until they get used to it. But we
draw lots of pictures and it doesn't take long for them to come around.
Of course the object-slicing of assignment from derived types to
basetypes tends to give them headaches (me too).
--John
> _______________________________________________
> Edu-sig mailing list
> Edu-sig at python.org
> http://mail.python.org/mailman/listinfo/edu-sig
--
John M. Zelle, Ph.D. Wartburg College
Professor of Computer Science Waverly, IA
john.zelle at wartburg.edu (319) 352-8360
More information about the Edu-sig
mailing list