2013-06-26 2 views
0

У меня действительно странная проблема. Ниже приведен пример кода:Список Python append вызывает странный результат

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?

Спасибо!

+1

Поскольку б указывает на, когда вы меняете, вы меняете б а – matino

ответ

6

Вы назначаете тот же список до 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 
+0

Просто, чтобы добавить второй метод self.b = список (я. a), пожалуйста, добавьте это также в ответ. –

+0

Спасибо! Решено! – user232343

1

dicts in python совместно используют одну и ту же память s когда вы назначаете их друг другу.

для получения дополнительной информации об этом см: http://henry.precheur.org/python/copy_list

+2

Это списки, а не словари. В списках do * not * есть метод '.copy()'. –

+0

моя ошибка Я отредактирую свой ответ – zidsal

2

self.b = self.a не копирование списка. Он назначает ссылку на этот список, поэтому оба атрибута указывают на один и тот же объект. Если вы измените его с помощью одной ссылки, вы увидите изменение через другое.

Вы можете использовать copy.copy(the_list), чтобы получить правильную копию. Или copy.deepcopy(the_list), если вам нужны ссылки ниже также обновлены.

+1

Объекты списка не имеют метода '.copy' – Blender

+0

@Blender Я предполагаю, что он имел в виду copy.copy (listname) –

+0

Да, извините, может быть более явным. Отредактировано сейчас. – viraptor

1

Потому что 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() 
7

Как многие уже говорили, вы в конечном итоге, две ссылки на же списке. Изменив список по одной ссылке другой, просто измените список.

Вот если требуется иллюстрация, чтобы сделать вещи более ясно:

Shared reference

  • Шаг "А" только после того, как

    self.a = [(1,2), (3,4)] 
    
  • Шаг "А" только после того, как

    self.b = self.a 
    
  • Шаг «C» только после того, как

    self.a.append((5,6)) 
    
+0

Как вы создавали эти изображения? –

+1

@AshwiniChaudhary Inkscape ... –

Смежные вопросы