Два имени указывают на один и тот же объект в python - PullRequest
1 голос
/ 07 августа 2020

Рассмотрим следующий пример:

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)

Вывод:

False
True
[3, 2, 1]

Пояснение :

Я создаю 2 объекта одного класса , а «список» каждого объекта - [1, 2, 3]. При проверке, ссылаются ли имена obj1, obj2 на один и тот же объект, ответ будет отрицательным (Ложь). Но когда я проверяю, соответствует ли obj1.list is obj2.list, мы получаем в качестве ответа «True». Таким образом, когда я переворачиваю список имени obj1, список также переворачивается на имя obj2, потому что это то же самое. list для обоих имен.

Мне нужен способ перевернуть список для obj1, но не для obj2. Поэтому мне нужно создать новый список.

В итоге будет результат:

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

Ожидаемый результат:

[1, 2, 3]

Ответы [ 2 ]

3 голосов
/ 07 августа 2020

Вы сохраняете ту же ссылку на список в self.list, чего можно избежать, сделав копию:

class Test:
    def __init__(self, lis: list):
        self.list = <b>lis[:]</b>

Считайте это указателем. Итак, когда вы изменяете одно, другое, указывающее на то же значение, также изменяется.

1 голос
/ 07 августа 2020

copy method in Python возвращает shallow copy of a list. Неглубокая копия означает, что: любое изменение, сделанное в новом списке, не повлияет на исходный список.

Например:

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

Результат:

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

В этом примере lis1 и lis2 относятся к одному и тому же адресу. Таким образом, любые изменения в одном из них приведут к изменениям и в другом.

Мы можем решить эту проблему, используя список copy method или copy module.

Например:

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

Вывод:

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

В этом примере lis2 является копией lis1, хранящейся по другому адресу, следовательно, когда мы меняем lis1 в lis2 изменений не наблюдается.

Аналогичным образом можно использовать модуль копирования. Например:

import copy

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

Вывод:

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

Аналогичным образом ваша проблема может быть решена с помощью 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)

Теперь возвращается желаемый результат. :

False
True
[1, 2, 3]

Надеюсь, это было полезно!

...