I am looking for the proper term to describe this well-known property of collection objects, and more importantly, the way the stack diagram changes when variables are used to reference their elements:
>>> x = 5
>>> l = [x]
>>> x += 1
>>> l
[5]
>>> x
6
What is the name of what the list is doing to the variable x
to prevent it from being bound to any changes to the original value of x
? Shielding? Shared structure? List binding? Nothing is coming back from a Google search using those terms.
Here's an example with more detail (but doesn't have a definition, unfortunately).
Credit to ocw.mit.edu
The behavior you're describing has to do with references. If you're familiar with c
, you're probably also familiar with "pointers." Pointers in c
can get really complicated, and Python uses a data model that greatly simplifies things. But having a bit of background in c
helps understand Python's behavior here, which is closely related to the behavior of c
pointers. So "pointer," "reference," and "dereference" are all terms that are related to what you're talking about, although none of them is quite a "name" for it. Perhaps the best name for it is "indirection" -- though that's a bit too abstract and inclusive; this is a very specific kind of indirection. Perhaps "reference semantics"? Here's a slide from a talk by GvR himself that uses that term, and a google search turns up a few useful hits.
But if you don't have any background in c
, here's my best explanation. In short, you can think of a Python name as a pointer to an object. So when you assign a name to a value, you're "pointing" that name at the value. Then, when you assign a new value to the name, you point it at a new value; but the old value isn't changed at all as a result. This seems natural when thinking about names as pointers here; the "value of the name" is changed, but the "value of the value" is not.
The thing that's a bit confusing is that +=
behaves inconsistently. When you use +=
on a number, the result makes perfect sense using the above metaphor:
x = 5
y = x
x += 1
print x, y
# 6 5
The behavior is exactly the same as it would be if you did x = x + 1
.
But sometimes +=
is overloaded in a way that does in-place mutation. It's a pragmatic, but slightly inconsistent, idiom:
x = [5]
y = x
x += [6]
print x, y
# [5, 6] [5, 6]
So here, the "value of the value" is changed. This is actually not my favorite thing about Python, but there are good reasons for it.