I'm new at python I have some Question about Variable thing.
I've heard that s refers to a variable, and s[:] refers to copying a value, not a reference.
Why do both results in the same way?
I thought if [:] did this, b would be hello and a would still be hellQ, but the result is not

- 95
- 7
-
If you want to get true copy, use `copy.deepcopy` – mvp Dec 20 '20 at 05:06
-
1@mvp This has nothing to do with deep vs. shallow copies, since there are no nested references in any of these examples. – Tom Karzes Dec 20 '20 at 05:09
-
1There is only one list, throughout this code. `b[:] = a` does absolutely nothing; it's exactly the same as `b[:] = b` (or `a[:] = a`), you're replacing the contents of the list with the contents that it already has. – jasonharper Dec 20 '20 at 05:10
-
2`b[:] = a` just replaces the contents of `b` with the contents of `a`. Since `a` and `b` refer to the same list, this effectively does nothing. If you want to create a copy of `a`, try `b = a[:]` instead, which is equivalent to `b = list(a)`. – Tom Karzes Dec 20 '20 at 05:11
-
Copying happens when you do `b = a[:]`. Also see [Difference between a[:] = b and a = b[:]?](https://stackoverflow.com/questions/7033499/difference-between-a-b-and-a-b-python). – Ishan Dec 20 '20 at 05:11
-
@tomkarzes, if he used deepcopy, it would behave how he wants it to – mvp Dec 20 '20 at 05:57
-
Change the line `b = a` to `b = a.copy()` and you'll be fine. Otherwise both variables will be referencing to the same object in memory. – Cainã Max Couto-Silva Dec 20 '20 at 06:53
-
@mvp Well, only in the sense that if he used `list.copy()` it would behave as desired. The point is that the list wasn't being copied, but was instead being modified directly. Either shallow or deep copy would have solved the problem. – Tom Karzes Dec 20 '20 at 08:45
-
@tomkarzes, so you just confirmed that it has everything to do with proper object copy – mvp Dec 20 '20 at 09:22
-
@mvp It has to do with copying vs. not copying, not "deep" vs. "shallow" copying. Shallow copy is perfectly adequate for OP's needs in this case, and there are about half a dozen ways to do it. Deep copy is overkill for this example, and distracts from the main problem, which is that assigning to a list slice does not do what OP desired. – Tom Karzes Dec 20 '20 at 10:30
2 Answers
When you assigned a
to b
first, you only have one actual list data on the heap, you should try to assign another list data on heap to b
first.
In your example, when you first assign ['h', 'e', 'l', 'l', 'o']
to a
, you are creating a variable a
pointing to the actual list data on heap. After that you assign a
to b
, which means creating a variable b
pointing to the data that the a
is pointing to, now the structure looks like this:
a ---> ['h', 'e', 'l', 'l', 'o']
^
|
b ------
Then, b[-1] = 'q'
means change the last element of the list data which b
is pointing to, which results in:
a ---> ['h', 'e', 'l', 'l', 'q']
^
|
b ------
After that, b[:] = a
means change the data of the list to which b
is pointing to the data of the list to which a
is pointing, which in this situation does nothing (a
and b
are still pointing to the same list data). Therefore, the following a[-1] = 'Q'
and b[-1] = 'o'
are just changing the (only) list data, which looks like:
a ---> ['h', 'e', 'l', 'l', 'Q']
^
|
b ------
a ---> ['h', 'e', 'l', 'l', 'o']
^
|
b ------
Back to the difference of b = a
and b[:] = a
, if you want to see how b[:] = a
is different from b = a
, you could first assign ['h', 'e', 'l', 'l', 'o']
to a
and assign another list []
to b, now the structure looks like:
a ---> ['h', 'e', 'l', 'l', 'o']
b ---> []
Then if you use b[:] = a
, which change the data of the list to which b
is pointing to the data of the list to which a
is pointing, you will get a structure like:
a ---> ['h', 'e', 'l', 'l', 'o']
b ---> ['h', 'e', 'l', 'l', 'o']
In this state, any change you made to the list to which a
is pointing won't affect the list to which b
is pointing. For instance, use a[-1] = 'Q'
now will only change the list to which a
is pointing, which results in a structure like:
a ---> ['h', 'e', 'l', 'l', 'Q']
b ---> ['h', 'e', 'l', 'l', 'o']

- 357
- 3
- 15
@SliAce is right.
b[:]
overwrites the contents of the list without creating a new reference.
a
and b
are refering to same list, So b[:] = a
does noting. It copy values from it own list(using reference a) to it own list.
And it's no need to use copy.deepcopy
, it's used to copy the element in the list which is mutable, like list or dict, in your situation, str is immutable, so it has created a new object.

- 1
- 1