Список Python додавання викликає дивний результат

У мене дуже дивна проблема. Ось код зразка:

class SomeClass(object):
    a = []
    b = []
    def __init__(self, *args, **kwargs):
        self.a = [(1,2), (3,4)]
        self.b = self.a
        self.a.append((5,6))
        print self.b

SomeClass()

Друк виходів [(1, 2), (3, 4), (5, 6)], але чому, чому результат не [(1,2), (3,4)]? Чи знаєте ви, як я можу мати стару цінність self.a в self.b?

Дякую!

0
Оскільки b вказує на a, коли ви змінюєте a, ви також змінюєте b
додано Автор matino, джерело
Оскільки b вказує на a, коли ви змінюєте a, ви також змінюєте b
додано Автор matino, джерело

6 Відповіді

Як багато хто вже згадували про це, ви отримаєте два посилання на той же список. Змінюючи список за одним посиланням іншого, просто змініть список .

Ось ілюстрація, щоб зробити речі яснішими, якщо необхідно:

Shared reference

  • Step "A" is just after

    self.a = [(1,2), (3,4)]
    
  • Step "A" is just after

    self.b = self.a
    
  • Step "C" is just after

    self.a.append((5,6))
    
7
додано
Як ви генерували ці зображення?
додано Автор Ashwini Chaudhary, джерело
@AshwiniChaudhary Inkscape ...
додано Автор Sylvain Leroux, джерело

Ви призначаєте той же список для self.b , а не копію.

Якщо ви хочете позначити self.b для копії списку, створіть його за допомогою list() або повного фрагмента:

self.b = self.a[:]

або

self.b = list(self.a)

Ви можете легко протестувати це з інтерактивного інтерпретатора:

>>> a = b = []  # two references to the same list
>>> a
[]
>>> a is b
True
>>> a.append(42)
>>> b
[42]
>>> b = a[:]  # create a copy
>>> a.append(3.14)
>>> a
[42, 3.14]
>>> b
[42]
>>> a is b
False
6
додано
Дякую! Вирішено!
додано Автор user232343, джерело
Для того, щоб додати другий метод self.b = list (self.a), додайте його також у відповідь.
додано Автор Ankit Jaiswal, джерело

Ви призначаєте той же список для self.b , а не копію.

Якщо ви хочете позначити self.b для копії списку, створіть його за допомогою list() або повного фрагмента:

self.b = self.a[:]

або

self.b = list(self.a)

Ви можете легко протестувати це з інтерактивного інтерпретатора:

>>> a = b = []  # two references to the same list
>>> a
[]
>>> a is b
True
>>> a.append(42)
>>> b
[42]
>>> b = a[:]  # create a copy
>>> a.append(3.14)
>>> a
[42, 3.14]
>>> b
[42]
>>> a is b
False
6
додано
Дякую! Вирішено!
додано Автор user232343, джерело
Для того, щоб додати другий метод self.b = list (self.a), додайте його також у відповідь.
додано Автор Ankit Jaiswal, джерело

self.b = self.a isn't copying the list. It's assigning the reference to that list, so both attributes point at the same object. If you modify it via one reference, you'll see the change via the other one too.

Ви можете використовувати copy.copy (the_list) , щоб отримати правильну копію. Або copy.deepcopy (the_list) , якщо вам потрібні посилання нижче, також оновлено.

2
додано
Так, вибачте, може бути більш явним. Відредаговано зараз
додано Автор viraptor, джерело
Список об'єктів не має методу .copy
додано Автор Blender, джерело
@ Блендер Я думаю, він мав на увазі copy.copy (listname)
додано Автор Ankit Jaiswal, джерело

Тому що self.a і self.b дійсно є посиланнями на один і той же об'єкт списку.

Якщо ви хочете змінити один, не змінюючи іншого, спробуйте це

class SomeClass(object):
    # a = []
    # b = [] # these two class member not necessary in this code
    def __init__(self, *args, **kwargs):
        self.a = [(1,2), (3,4)]
        self.b = list(self.a) # copy to a new list
        self.a.append((5,6))
        print self.b

SomeClass()
1
додано

dicts в python поділяють той самий простір пам'яті, коли ви призначаєте їх один одному.

for more information on this see: http://henry.precheur.org/python/copy_list

1
додано
Це списки, а не словники. Списки не мають метод .copy() .
додано Автор Martijn Pieters, джерело
моя помилка я відредагую свою відповідь
додано Автор zidsal, джерело
ІТ КПІ - Python
ІТ КПІ - Python
625 учасників

Канал обговорень про всякі штуки зі світу пайтону. Прохання: 0. мати повагу одне до одного; 1. не матюкатися в сторону людей; 2. не захламляти тред повідомленнями по одному слову;