Clarification on Immutability please
Cameron Simpson
cs at cskk.id.au
Tue Jan 21 17:15:36 EST 2020
On 21Jan2020 17:40, Stephen Tucker <stephen_tucker at sil.org> wrote:
>I am sure this has been answered many times before, but I need to ask
>it
>again.
>
>Given that the following is valid Python 2.7.10 (when keyboarded into Idle):
>
>mytup = ("q", "w", "e")
>id(mytup)
>mytup = mytup [:2]
>id(mytup)
>
>and even that the first id(mytup) returns the same address as the second
>one,
Really? Not here:
[~]fleet*> python2.7
Python 2.7.16 (default, Apr 1 2019, 15:01:04)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> mytup = ("q", "w", "e")
>>> id(mytup)
4541315104
>>> mytup = mytup [:2]
>>> id(mytup)
4542334880
>>>
>I am left wondering exactly what immutability is.
Immutability generally means that the direct contents of the object may
not be changed:
>>> mytup = (1,2,3)
>>> mytup[1]
2
>>> mytup[1] = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
It doesn't say anything about the contents of the internal objects:
>>> mytup = (1, [2, 3], (4, 5))
>>> mytup[0] = 6
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> mytupl[1] = [7, 8]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'mytupl' is not defined
>>> mytup[1].append(10)
>>> mytup
(1, [2, 3, 10], (4, 5))
>>> mytup[2].append(11)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
So you can see that I may modify the content of the list at mytup[1].
However, I can't replace mytup[1] with another list, because mytup
_itself_ is immutable.
>I am left concluding that mytup is not actually a tuple (even though type
>(mytup) tells me that it is).
>
>My only explanation is that mytup is, actually, a pointer to a tuple; the
>pointer can't change, but the contents of that pointer (or the data to
>which the pointer points) can change.
Ah. You're confusing the variable "mytup" with the object which it
references.
"mytup" is a Python variable, which is reference to some object (a lot
like a pointer conceptually, but not a pointer - a "pointer" is a memory
address - so say "reference" and not "pointer" and people here will be
happier).
Here, "mytup" refers to a tuple object. "type(mytup)" accesses that
object and tells you its type (a tuple). You can change "mytup":
mytup = [1, 2, 3]
which causes it to refer to a different object. By you can't change the
direct references in the original tuple object (eg mytup[1]).
>That said, if I then type
>
>mytup = mytup + ("r", "t")
>id(mytup)
>
>I find that this third id call returns a different address from the one
>returned by the first two.
A newtuple has been created, and "mytup" and been changed to refer to
the new object.
>Somehow, it seems, tuples can be reduced in length (from the far end)
>(which is not what I was expecting), but they cannot be extended (which I
>can understand).
No, you're seeing new tuples of different lengths. "mytup" is just being
switched around by the assignment statement to refer to the new tuples.
If you're familiar with "pointers" in C-like languages, where a pointer
variable holds the address of something, think of Python variables as
somewhat like those. They're a little more complex but the behaviour is
similar. Here "mytup" is like a pointer variable in C, and the tuple is
the "something" to which it points. The tuple is immutable, not the
pointer.
Why do we distinguish between "pointer" and "reference", particularly
which CPython does a lotof this internally with C pointers (id() in
CPython returns an address as it happens)? Because there are multiple
implementations of Python, and they needn't use C-like pointers
internally. Imagine the id() was an index into some table-of-objects and
that the table itself held pointers, eg so that the object storage
itself could be moved around.
So Python variables are references. The variables themselves are not
immutable.
Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)
Draw little boxes with arrows. It helps. - Michael J. Eager
More information about the Python-list
mailing list