How to Copy a List

How do I clone a list so that it doesn't change unexpectedly after assignment?

new_list = my_list doesn't actually create a second list. The assignment just copies the reference to the list, not the actual list, so both new_list and my_list refer to the same list after the assignment.

To actually copy the list, you have several options:

  • You can use the builtin list.copy() method (available since Python 3.3):

    new_list = old_list.copy()
  • You can slice it:

    new_list = old_list[:]

    Alex Martelli's opinion (at least back in 2007) about this is, that it is a weird syntax and it does not make sense to use it ever. ;) (In his opinion, the next one is more readable).

  • You can use the built in list() constructor:

    new_list = list(old_list)
  • You can use generic copy.copy():

    import copy
    new_list = copy.copy(old_list)

    This is a little slower than list() because it has to find out the datatype of old_list first.

  • If you need to copy the elements of the list as well, use generic copy.deepcopy():

    import copy
    new_list = copy.deepcopy(old_list)

    Obviously the slowest and most memory-needing method, but sometimes unavoidable. This operates recursively; it will handle any number of levels of nested lists (or other containers).

Example:

import copy

class Foo(object):
def __init__(self, val):
self.val = val

def __repr__(self):
return f'Foo({self.val!r})'

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# edit orignal list and instance
a.append('baz')
foo.val = 5

print(f'original: {a}\nlist.copy(): {b}\nslice: {c}\nlist(): {d}\ncopy: {e}\ndeepcopy: {f}')

Result:

original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]

What is the best way to copy a list?

If you want a shallow copy (elements aren't copied) use:

lst2=lst1[:]

If you want to make a deep copy then use the copy module:

import copy
lst2=copy.deepcopy(lst1)

How to copy a list of lists in Python?

As quamrana mentions, you can use deepcopy.

import copy

a = [[1,2],[3,4]]
b = copy.deepcopy(a)

Taken from here.

How to copy the elements of the list within the list?

from copy import deepcopy

def multiply_list_elem(lst, n):
out = list()
for elem in lst:
for _ in range(n):
out.append(deepcopy(elem))
return out

if __name__ == '__main__':
list_1 = [[1,2,3], [4,5,6], [7,8,9]]
print(multiply_list_elem(list_1, 2))

Python copy a list of lists

From the docs for the copy module:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

When you call regular copy.copy() you are performing a shallow copy. This means that in a case of a list-of-lists, you will get a new copy of the outer list, but it will contain the original inner lists as its elements. Instead you should use copy.deepcopy(), which will create a new copy of both the outer and inner lists.

The reason that you didn't notice this with your first example of using copy([1,2]) is that the primitives like int are immutable, and thus it is impossible to change their value without creating a new instance. If the contents of the list had instead been mutable objects (like lists, or any user-defined object with mutable members), any mutation of those objects would have been seen in both copies of the list.

Copy a list of list by value and not reference

Because python passes lists by reference

This means that when you write "b=a" you're saying that a and b are the same object, and that when you change b you change also a, and viceversa

A way to copy a list by value:

new_list = old_list[:]

If the list contains objects and you want to copy them as well, use generic copy.deepcopy():

import copy
new_list = copy.deepcopy(old_list)

How to clone or copy a list whose element is list, in python?

import copy

lis = [[1], [2]]

deep_list = copy.deepcopy(lis)
copy_list = copy.copy(lis)

print(deep_list is lis)
print(deep_list[0] is lis[0])
print(deep_list[1] is lis[1])

print(copy_list is lis)
print(copy_list[0] is lis[0])
print(copy_list[1] is lis[1])

In the above code deepcopy() creates a deep copy of the list so you and copy() creates a shallow copy. In case of deepcopy() the list's within the list will also be copied.

OUTPUT:

False
False
False
False
True
True

EDIT: Since you cant import library may be you can try below approach:

lis = [[1], [2]]

deep_list = []

for item in lis:
deep_list.append(item[:])

print(deep_list is lis)
print(deep_list[0] is lis[0])
print(deep_list[1] is lis[1])

OUTPUT:

False
False
False

How to copy List items from two different List objects

You can use Stream#map like so:

List<InUseObject> list2 = list1.stream()
.map(obj -> new InUseObject(obj.getId(), obj.getPropertyname(), obj.getPropertyvalue()))
.collect(Collectors.toList());

You can also define a constructor in InUseObject accepting a TemplateObject:

public InUseObject(final TemplateObject obj) {
this(obj.getId(), obj.getPropertyname(), obj.getPropertyvalue());
}

You can then use a constructor reference when mapping.

List<InUseObject> list2 = list1.stream()
.map(InUseObject::new)
.collect(Collectors.toList());

How to deep copy a list?

E0_copy is not a deep copy. You don't make a deep copy using list(). (Both list(...) and testList[:] are shallow copies.)

You use copy.deepcopy(...) for deep copying a list.

deepcopy(x, memo=None, _nil=[])
Deep copy operation on arbitrary Python objects.

See the following snippet -

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

Now see the deepcopy operation

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]

To explain, list(...) does not recursively make copies of the inner objects. It only makes a copy of the outermost list, while still referencing the same inner lists, hence, when you mutate the inner lists, the change is reflected in both the original list and the shallow copy. You can see that shallow copying references the inner lists by checking that id(a[0]) == id(b[0]) where b = list(a).



Related Topics



Leave a reply



Submit