-2

I am having some trouble with Python, I know in other languages everything you do is pretty straight forward and very logical. However, in Python, appending a list with data to a new list simply keeps a reference or pointer, and as a result, any changes made to the original list are apparent in the new list.

I have heard about copy.copy(list[:]), but I am not 100% percent sure this would work well.

list_1 = [1, 2, 3]
new_list = []
new_list.append(list_1[:])

However, if you modify list_1, you also modify new_list, since they point to the same list.

>>> list_1.append(4)

>>> print list_1
[1, 2, 3, 4]

>>> print new_list
[1, 2, 3, 4]

All of this is really annoying to me. If anyone knows a better way, please tell me.

I want to be able to make changes to the list_1 and continue to append to the new_list, so that I populate the new_list like this:

new_list
[0] >>>
    [1, 2, 3, 4]
[1] >>>
    [5, 6, 7, 8]

And sometimes the first list can also be larger than what claimed by this example.

Made a test run now:

Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> list_1 = [1,2,3]
>>> new_list = []
>>> new_list.append(list_1[:])
>>> print new_list
SyntaxError: Missing parentheses in call to 'print'
>>> print(new_list)
[[1, 2, 3]]
>>> list_1.append(4)
>>> print(new_list)
[[1, 2, 3]]
>>> print(new_list)
[[1, 2, 3]]
>>> print(list_1)
[1, 2, 3, 4]

Strange. Strange. Strange.

haxxir411
  • 79
  • 1
  • 1
  • 8
  • `new_list.append(list_1[:])` => `new_list = [[1, 2, 3]]`. `[:]` _does_ make a copy, so I don't understand your question. We'd need a [mcve] – Jean-François Fabre Dec 28 '16 at 10:45
  • Why didn't you get a nested list for `new_list`? This code works if I understand it correctly – martianwars Dec 28 '16 at 10:45
  • @Jean-FrançoisFabre, and you have a MCV right in this code. See for yourself, in my code example. – haxxir411 Dec 28 '16 at 10:47
  • Possibly related: http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list – Arc676 Dec 28 '16 at 10:48
  • as said above, the output of your code doesn't match the code. I saw that without testing, but made a test to make sure. Now I'm sure. It's nonsense. Please post a standalone code snippet that demonstrates the problem. – Jean-François Fabre Dec 28 '16 at 10:48
  • @haxxir411 Jean is right. Your code already works for me as well. – Mohammad Yusuf Dec 28 '16 at 10:49
  • I agree that Python's data model _can_ be weird, confusing and even annoying when you first encounter it if you have experience with other languages that use the more traditional data model. But after a while you will (hopefully :) ) come to appreciate it. In the mean time, you may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Dec 28 '16 at 10:53
  • (cont) For a very brief summary with cute diagrams please see [Other languages have "variables", Python has "names"](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables) – PM 2Ring Dec 28 '16 at 10:53
  • 2
    Well, the last example shows that `[:]` _does_ make a copy of the list, so what's the problem? – ForceBru Dec 28 '16 at 10:58

1 Answers1

-1

In Python any complex object is always represented by its reference. By complex I mean not bool, int, float, NoneType and other base data types. This is why, two references may point to one object, and any modification using one reference will lead to the same changes shown throught the other reference:

>>> lst = [1, 2]
>>> lst2 = lst
>>> lst.append(3)
>>> lst2
[1, 2, 3]

If you want to have two different objects you should clone the first one. It can be done by copy.copy or copy.deepcopy depending on what you actually need:

>>> import copy
>>> lst = [1, 2]
>>> lst2 = copy.copy(lst)
>>> lst.append(3)
>>> lst
[1, 2, 3]
>>> lst2
[1, 2]
Fomalhaut
  • 8,590
  • 8
  • 51
  • 95
  • 1
    What? In Python, even primitive data types like bool, int, float, etc are fully-fledged objects. So when you do `a = 42` you bind the `int` object with the value of 42 to the name "a"; essentially, "a" is a key associated with a pointer to the `int` object. But I find it's best _not_ to think about Python in terms of pointers, references, etc: try to embrace the Python data model on its own terms. – PM 2Ring Dec 28 '16 at 11:13
  • @PM2Ring I know that. And my explanation doesn't contradict you. Above I was trying a way how to explain it in simple words. I think, my explanation is quite understandable and may help the author. – Fomalhaut Dec 28 '16 at 11:20
  • @Fomalhaut 1. the term "reference" has a well defined meaning in other languages, that doesn't match how Python works, and 2/ Python bindings work the same for __all__ types - whether builtin or not, mutable or not, whatever, they are __all__ objects, period. – bruno desthuilliers Dec 28 '16 at 11:26
  • This such a non answer. – Jean-François Fabre Dec 28 '16 at 14:33