10

I'm very new to Python, so sorry for the probably simple question. (Although, I spent now 2 hours to find an answer)

I simplified my code to illustrate the problem:

side=[5]
eva=side
print(str(side) + " side before")
print(str(eva) + " eva before")
eva.remove(5)
print(str(side) + " side after")
print(str(eva) + " eva after")

This yields:

[5] side before
[5] eva before
[] side after
[] eva after

Why does the remove command also affects the list 'side'? What can I do to use a copy of 'side', without modifying the list?

Thank you very much

Edit: Thank you very much for the good and comprehensible answers!

Sevik
  • 111
  • 6
  • 2
    You've run into the idea of names in python. http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#python-has-names – GoingTharn Mar 08 '12 at 17:42
  • 1
    @GoingTharn *Namespaces* are a quite different matter. He's run into the fact that there are no value types in Python (and yes, that can be described in a gazillion other ways too - but "namespaces" isn't among them). –  Mar 08 '12 at 17:43
  • @delnan agreed; I realized with horror I'd written namespaces and edited to names. Dusan's link in the (current) top voted answer is better than mine anyhow. – GoingTharn Mar 08 '12 at 17:47

3 Answers3

13

Python has "things" and "names for things". When you write

side = [5]

you make a new thing [5], and give it the name side. When you then write

eva = side

you make a new name for side. Assignments are just giving names to things! There's still only one thing [5], with two different names.

If you want a new thing, you need to ask for it explicitly. Usually you would do copy.copy(thing), although in the case of lists there's special syntax thing[:].

FYI "things" are usually called "objects"; "names" are usually called "references".

Katriel
  • 120,462
  • 19
  • 136
  • 170
11

eva and side refer to the same list.

If you want to have a copy of the list:

eva = side[:]

You can read more about copying lists in this article: Python: copying a list the right way

Edit: That isn't the only way to copy lists. See the link posted in the first comment of this answer.

dusan
  • 9,104
  • 3
  • 35
  • 55
1

dusan's answer is correct, and is a clever approach, but I think it breaks the Zen of Python guideline that "Explicit is better than implicit."

A far more common pattern I've seen to ensure an item is a deepcopy is with the copy module.

>>> import copy
>>> eva = copy.copy(side)
Community
  • 1
  • 1
mvanveen
  • 9,754
  • 8
  • 33
  • 42
  • 4
    I don't think it breaks the explicitness guideline. It is _explicitly_ copying! Opaque syntax, maybe. – Katriel Mar 08 '12 at 17:46
  • 4
    Also note `copy.copy` does the same as `[:]`, not `copy.deepcopy`. – Katriel Mar 08 '12 at 17:47
  • The two are different use cases. You don't necessarily always want to make copies of the items in the list. – Casey Kuball Mar 08 '12 at 17:50
  • 4
    `side[:]` *is* idiomatic Python. – Steven Rumbalski Mar 08 '12 at 18:42
  • 3
    To back up my prior comment I `os.walk`'d all python files in the Python 2.7 source Lib directory. In 1,540 files, `copy.copy` or `copy.deepcopy` were used 132 times. `[:]` appeared 441 times, but was used to copy 176 times. So `[:]` is no less idiomatic than using `copy.copy`. – Steven Rumbalski Mar 08 '12 at 19:04
  • Wow! Thanks for that information! It's refreshing to have frequency counts in semantic discussions like this. To be honest, I had never seen `[:]` before now. I would hazard that not everything in the stdlib is idiomatic (there are some awful practices hidden away in some libraries), but I totally agree with your claim that both are "idiomatic" after reading your counts. – mvanveen Mar 11 '12 at 01:22
  • @katrielalex, thanks for catching my `copy` vs `deepcopy` goof. – mvanveen Mar 11 '12 at 01:24