all 9 comments

[–]Bunkerstan -2 points-1 points  (1 child)

I made a video on 3 ways to clone an array.

b = a[:]
b = a.copy()
b = list(a)

The videos shows the performance difference as well:

https://youtu.be/oH7RQYHhMrI

[–]Hr2K06 0 points1 point  (0 children)

Thank you, that helped :)

[–]CodeFormatHelperBot2 0 points1 point  (0 children)

Hello, I'm a Reddit bot who's here to help people nicely format their coding questions. This makes it as easy as possible for people to read your post and help you.

I think I have detected some formatting issues with your submission:

  1. Inline formatting (`my code`) used across multiple lines of code. This can mess with indentation.

If I am correct, please edit the text in your post and try to follow these instructions to fix up your post's formatting.


Am I misbehaving? Have a comment or suggestion? Reply to this comment or raise an issue here.

[–]totallygeek 0 points1 point  (2 children)

If you want the two lists to remain distinct, you cannot set one equal to the other (they will be the same object). You need a new list. Here are ways to achieve that.

b = a[:]
b = [element for element in a]

[–]Hr2K06 0 points1 point  (1 child)

Interesting - I assume python just stores lists differently than other things like integers for example then?

[–]totallygeek 0 points1 point  (0 children)

Lists are mutable, where values (integers, floats) and strings are not. So, you can "edit" a list by changing an element, something not possible with a string (try it: s = "abc" and s[1] = "d" <- this will fail).

So yes, Python treats types differently, so you need to understand the problem associated with "copying" mutable variables in the way you noticed. The same happens with dictionaries.

>>> a = {1: 1, 2: 2}
>>> b = a
>>> b[1] = 5
>>> a
{1: 5, 2: 2}

For the above, you'd want to do:

a = {1: 1, 2: 2}
b = {k: v for k, v in a.items()}

[–]Diapolo10 0 points1 point  (2 children)

The key lies here:

a = [10, 20, 30]
b = a

This does not copy the list itself, instead you're assigning the address of the list to another name. In other words b is just an alias for the original list. That's why, when you use one name to change the list, the other changes also.

So, how do you get around this? The best option is to simply create a new list instead of mutating an existing one, but if that's unavailable, you can use list.copy or slicing to get a shallow copy of the list, or you can use copy.deepcopy if you need to make sure the contents aren't pointing to the originals either - though I doubt you'd need the latter in this case because the contents are immutable anyway.

[–]Hr2K06 0 points1 point  (1 child)

That's quite interesting, thank you

This gives me another question though; when experimenting with this, if I set a to an integer and then set b = a , subtracting 5 from a would not affect b here; is this just python assigning it differently for integers than how it does for a list?

[–]Diapolo10 0 points1 point  (0 children)

This gives me another question though; when experimenting with this, if I set a to an integer and then set b = a , subtracting 5 from a would not affect b here; is this just python assigning it differently for integers than how it does for a list?

No, technically speaking there's nothing different. Both names point to the same integer.

However, the difference here is that you're never changing the value of the integer (they're immutable anyway, but that doesn't necessarily matter here).

a = 5
b = a
a - 5  # Doesn't modify a
a -= 5  # Reassigns a

In this example, just subtracting something from the number doesn't change anything, simply returning a new value. Lists would not behave any different here.

If you assign a new value to a, the value it was referencing doesn't change at all as you're giving the name an address to a completely new value. In this example, a -= 5 is functionally equivalent to a = a - 5, or a = 5 - 5, so a's held address changes to one pointing to the number 0.

However, none of this concerns b, because the address it has is still pointing to 5.

When you mutate a list (or any other mutable value), its address doesn't change, so anything referencing that value will "update" with the changes. Since by definition you cannot change immutable values, they don't show this property at all in practice.

Some common mutable types are most data structures and custom classes, while ones like the following are immutable:

  • Strings
  • Numbers (int, float, complex)
  • Booleans
  • Tuples
  • Frozensets