|
From: Bruce S. <bas...@un...> - 2002-10-04 12:15:22
|
A VPython user sent me a small program that behaved oddly, and I thought I
should share my analysis, since it involves an aspect of Python that is
subtle and may be missed in early study of the language. Fortunately it
rarely bites students writing computational physics programs!
Early in the program the user said "rinitial = ball.pos" which means "assign
an additional name to ball.pos, so that in the future one can refer to the
ball's position either by the label (name) ball.pos or the label (name)
rinitial". You can have lots of names pasted onto the same thing. The puzzle
for the user was that later in the program (after moving the ball around),
printing rinitial showed the new value of ball.pos, not the initial value.
This multiple labeling has consequences only with "mutable" objects such as
lists -- objects whose values can be changed in situ. For example, if you
say "a = 5" and then "b = a", and then say "a = 7", b will still have the
value 5. When you assign 7 to a, you create a new object ("7") and attach
the label "a" to it, so b continues to be a label for the object "5".
But with "rinitial = ball.pos", you can actually change ball.pos without
creating a new object. For example, you might say "ball.pos.y = 7" in which
case the 2nd element in the ball.pos list has changed (without affecting the
other two elements). Since rinitial is a label for ball.pos, printing
rinitial shows you the new value of ball.pos.
A list such as [1,2,3] is mutable. The Visual vectors are mutable. A 'tuple'
such as (1,2,3) is not mutable. Constants such as 3 or pi or a string such
as 'cat' are not mutable.
Needless to say, it took me a while to pay attention to "mutability" as an
important property of Python objects!
Bruce
|