2015-02-03 4 views
2

Я должен сказать, что у меня действительно нет проблемы, так как «все работает нормально», но я изо всех сил пытаюсь понять, почему.Непонятное поведение переменных класса

Я пишу скрипт в python/urwid. В моем сценарии у меня есть класс ItemWidget, чья self._w равна urwid.Pile из 3 виджетов, каждая из которых является строкой urwid.Text. Кроме того, класс ItemWidget имеет свойство self.visibility, которое представляет собой список из трех булевых элементов и метод self.rebuild(). Функция инициализации является

def __init__ (self, content,vis): 
    self.content = content 
    self.visibility = vis 
    self.rebuild() 
    self.__super.__init__(self._w)  

Способ восстановления() перестраивает self._w в зависимости от значений в self.visibility().

В основной функции() сценария у меня есть переменная

globalvisibility = [1,1,1] 

и создать список (примерно 1000) экземпляров ItemWidget:

for content in abstracts:        # (*) 
    items.append(ItemWidget(content,globalvisibility)) # 

На самом деле я использовал переменная, а не

for content in abstracts.items():       
    items.append(ItemWidget(content,[1,1,1]))    

только потому, что позже я реализую сохранение globalvisibility в файл. Но я не думал, что это будет полезно для чего угодно, кроме этой инициализации.

Во всяком случае, в сценарии я часто беру экземпляр ItemWidget и изменить его видимость с помощью, например

item.visibility[2] = 0 # (**) 

и подобные. До этого момента все работает нормально и, как ожидалось.

Вот мой вопрос. Почему после создания экземпляров ItemWidget через (*) изменение переменной globalvisibility, скажем, [0,1,1] влияет на все эти экземпляры?

Я должен сказать, что я «обнаружил» это случайно, и это кажется очень полезным (я думал, что для изменения видимости всех экземпляров ItemWidget мне придется перебирать все их), но - для меня - чрезвычайно удивительно. Особенно учитывая, что операции (**) затрагивают только отдельные экземпляры.

Я очень благодарен за объяснения.

EDIT: Весь сценарий здесь: https://www.dropbox.com/s/a0a4a0asyi5lyxw/tescik.py?dl=0 и пример базы данных, из которой я создать экземпляры, если itemwidget является: https://www.dropbox.com/s/zuwbvggznst85ru/arxiv-2013-05-23.db?dl=0

Для того, чтобы запустить его вам нужно изменить строку 58, чтобы указать базы данных. Чтобы увидеть поведение, выделите некоторые элементы и нажмите enter - тезисы исчезнут только на этих элементах, затем нажмите «показать тезисы» - это приведет к сбросу поведения для всех элементов.

+0

Поскольку все ваши экземпляры используют один и тот же объект списка. –

+1

Только для того, чтобы понять, где проблема: выводит ли файл 'a = [1,2,3]; b = a; a.append (4); print (b); 'также удивите вас? – DSM

+0

@ DSM: позвольте мне сказать так: меня удивляет, что я могу изменить свойство vis через (**) в конкретных случаях (разные экземпляры имеют разные значения), но тогда, когда я устанавливаю глобальную видимость на что-то, тогда все они перезагружаются то же самое –

ответ

2

Почему после создания экземпляров ItemWidget через (*) изменение переменной globalvisibility, скажем, [0,1,1] влияет на все эти экземпляры?

Поскольку вы прошли globalvisibility при создании всех этих экземпляров. Все экземпляры хранят ссылку на тот же список в свой атрибут vis.

Если вы хотите, чтобы избежать этого, скопировать список, либо в методе __init__ или при создании экземпляров:

def __init__ (self, content,vis): 
    self.content = content 
    self.visibility = vis[:] # here 
    # etc. 

Или:

for content in abstracts: 
    items.append(ItemWidget(content, globalvisibility[:])) 

Точный выбор вы делаете здесь, зависит от будет ли вы когда-либо хотеть текущего поведения. Если это так, оставьте его вне __init__() и сделайте копию при создании экземпляров.

+0

Thx Kindall, я понимаю, что все экземпляры хранят ссылку на один и тот же список в атрибуте vis. Но потом я могу изменить их в конкретных случаях через (**). Я имею в виду, что я вижу результат на своем экране, и примеры явно ведут себя так, как будто у них разные взгляды. Только когда я изменяю глобальную видимость, все они каким-то образом возвращаются к этой общей стоимости. Не могли бы вы объяснить, как это происходит? –

+0

Нет, я не могу. В Python нет ничего, что позволило бы вам описать то, что вы описали. – kindall

+0

Kindall, я верю, что вы говорите правду, но я до сих пор не понимаю. Не могли бы вы взглянуть на мой сценарий? Я разместил ссылку выше. –

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