1

Consider the following example:

class Test:
    def __init__(self, lis: list):
        self.list = lis


lis = [1, 2, 3]
obj1 = Test(lis)
obj2 = Test(lis)

print(obj1 is obj2)
print(obj1.list is obj2.list)

obj1.list.reverse()
print(obj2.list)

Output :

False
True
[3, 2, 1]

Explanation:

I create 2 objects of the same class,and the "list" of each object is [1, 2, 3]. Testing if the names obj1,obj2 are referencing the same object the answer is negative (False). But when I test if obj1.list is obj2.list, we get 'True' as an answer.Thus when I reverse the list of the name obj1,the list is also reversed of the name obj2, because it is the same list for both names.

What I need is a way to reverse the list for obj1, but not for obj2. So I need to create a new list.

In the end,this will be the result:

obj1.list.reverse()
print(obj2.list)

Expected output:

[1, 2, 3]
Anshika Singh
  • 994
  • 12
  • 20
Ermolai
  • 303
  • 4
  • 15

2 Answers2

3

You are storing the same reference to list in self.list, which you can avoid by making a copy:

class Test:
    def __init__(self, lis: list):
        self.list = lis[:]

Consider it as a pointer. So, when you modify one, the other which is pointing to the same value also changes.

Austin
  • 25,759
  • 4
  • 25
  • 48
  • This worked perfectly.I can't accept your answer yet,due to time restrictions,but i will in 10 minutes.Thank you :) – Ermolai Aug 07 '20 at 03:03
  • 2
    Reader beware: this creates a shallow copy. If the list is nested, then the nested elements will not be copied. The OP here is using flat lists so a shallow copy is fine, but for nested lists, it's probably best to use `copy.deepcopy`. – jkr Aug 07 '20 at 03:03
  • 2
    @jakub: it's probably not worth to use `deepcopy` for a flat list. Hence, suggested a shallow one. – Austin Aug 07 '20 at 03:05
2

The copy method in Python returns a shallow copy of a list. Shallow copy means that: any modification made in the new list won’t affect the original list.

For example:

lis1=['a','b','c']
print(lis1)
lis2=lis1
print(lis2)
lis1.pop()
print(lis1, lis2)

The output is:

['a', 'b', 'c']
['a', 'b', 'c']
['a', 'b'] ['a', 'b']

In this example, the lis1 and lis2 refer to the same address. Thus any changes in either of them will result in changes in the other as well.

We can solve this problem by using the copy method of list or by using the copy module.

For example:

lis1=['a','b','c']
print(lis1)
lis2=lis1.copy()
print(lis2)
lis1.pop()
print(lis1, lis2)

Output:

['a', 'b', 'c']
['a', 'b', 'c']
['a', 'b'] ['a', 'b', 'c']

In this example, the lis2 is a copy of the lis1 stored at a different address hence when we change lis1 no change is seen in lis2.

Similarly copy module can be used too. For example:

import copy

lis1=['a','b','c']
print(lis1)
lis2=copy.copy(lis1)
print(lis2)
lis1.pop()
print("list1=",lis1,"list2=", lis2)

Output:

['a', 'b', 'c']
['a', 'b', 'c']
list1= ['a', 'b'] list2= ['a', 'b', 'c']

Similarly your problem can be solved using copy method.

class Test:
    def __init__(self, lis: list):
        self.list = lis

lis = [1, 2, 3]
obj1 = Test(lis)
obj2 = Test(lis)
obj2new=obj2.list.copy()

print(obj1 is obj2)
print(obj1.list is obj2.list)

obj1.list.reverse()
print(obj2new)

Now, the desired output is returned:

False
True
[1, 2, 3]

Hope this was helpful!

Anshika Singh
  • 994
  • 12
  • 20