Reputation: 120
I have a really simple question about references in python.
I assume you are familiar with this:
aa = [1,2]
bb = aa
aa[0] = 100
print(bb)
As you might guess, the output will be
[100, 2]
and it's totally OK ✔
Let's do another example:
l = [[],[],[]]
a = l[0]
l[0] = [1,2]
print(a)
But here the output is:
[]
I know why that happened.
It's because, on line 3, we made an entirely different list and "replaced it"(not changing but replacing) with l[0]
Now my question is "Can I somehow replace l[0]
with [1,2]
and also keep a
as a reference?
P.S not like l[0].append(1,2)
Upvotes: 1
Views: 286
Reputation: 2122
Short answer: Not really, but there might be something close enough.
The problem is, under the covers, a
is a pointer-to-a-list, and l
is a pointer-to-a-list-of-pointers-to-lists. When you a = l[0]
, what that actually translates to at the CPU is "dereference the pointer l
, treat the resulting region of memory as a list object, get the first object (which will be the address of another list), and set the value of pointer a
to that address". Once you've done that, a
and l[0]
are only related by concidence; the are two separate pointers that happen, for the moment, to point at the same object. If you assign to either variable, you're changing the value of a pointer, not the contents of the pointed-to object.
Broadly speaking, there's a few ways the computer could practically do what you ask.
append
function does, along with the many other mutators of python lists. If you want to do this in a way that perhaps more clearly expresses your intent, you could do l[0][:] = [1,2]
. That's a list copy operation, copying into the object pointed to by both l[0]
and a
. This is your best bet as a developer, though note that copy operations are O(n).a
as a pointer-to-a-pointer-to-a-list that is automatically dereferenced (to merely a pointer-to-list) when accessed. This is not, AFAIK, something Python provides any support for; almost no language does. In C you could say list ** a = &(l[0]);
but then any time you want to actually do anything with a
you'd have to use *a
instead.a
is an alias to l[0]
, rather than its own, separate variable. As far as I know, Python doesn't support this either. In C, you could do it as #define a (l[0])
though you'd want to #undef a
when it went out of scope.a
a list variable (which is implemented as a pointer-to-list), make it a function: a = lambda: l[0]
. This means you have to use a()
instead of a
anywhere you want to get the actual content of l[0]
, and you can't assign to l[0]
through a()
(or through a
directly). But it does work, in Python. You could even go so far as to use properties, which would let you skip the parentheses and assign through a
, but at the cost of writing a bunch more code to wrap the lists (I'm not aware of a way to attach properties to lists directly, though one might exist, so you'd instead have to create a new object wrapping the list).Upvotes: 2
Reputation: 866
If a = l then calling a[0] in that case would yield [1,2], however, you are deleting the list that “a” was referencing, therefore the reference is destroyed as well. You need to either make a = l and call a[0] or reset the reference by calling a = l[0] again.
Upvotes: 1
Reputation: 2143
The original array at l[0] and the [1,2] array are two different objects. there is no way to do that short of re-assigning the a variable to l[0] again once the change has been made.
Upvotes: 0