Erfan Paslar
Erfan Paslar

Reputation: 120

Really simple question about reference of list in python

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

Answers (3)

CBHacking
CBHacking

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.

  1. Modify the pointed-to object (list) without modifying either pointer. That's what the 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).
  2. Implement 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.
  3. Tell the interpreter to observe that 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.
  4. Rather than making 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

Cmd858
Cmd858

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

LhasaDad
LhasaDad

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

Related Questions