2017-01-31 4 views
0

Привет, у меня есть класс со списком в качестве атрибута. Когда я создаю этот класс, я хочу изменить порядок этого списка для этого экземпляра. Например:Python переупорядочивает список атрибутов класса при инициализации

class A(object): 

    my_list = [1,2,3,4,5] 

    def __init__(self, first): 
     self.reorder_list(first) 

    def reorder_list(self, first): 
     self.my_list.insert(
      0, 
      self.my_list.pop(
        self.my_list.index(first) 
      ) 
     ) 

Это необходимо сделать следующее:

a = A(3) 
a.my_list 
[Out]: 3,1,2,4,5 

b = A(4) 
b.my_list 
[Out]: 4,1,2,3,5 

т.д.

Это похоже на работу .... Но не всегда ... Как и в итоге не соответствует. Когда я делаю это так:

def __init__(self, first): 
    self.my_list = self.reorder_list(first) 

def reorder_list(self, first): 
    my_copy = copy.copy(self.my_list) 
    ... do reordering on my_copy ... 
    return my_copy 

Затем он работает последовательно.

Может кто-нибудь объяснить мне, почему мой первый фрагмент кода - это не способ сделать это, и если мой второй способ сделать это (с копией, а затем с reassinging self.my_list) - правильный способ сделать это?

+0

ваш пример не работоспособной, вы пропустили параметр самодостаточности в reorder_list? – Jul3k

+0

Вы правы, я добавил его. – RvL

ответ

1

Когда вы назначаете значение атрибуту класса в Python, это значение является общим для всех экземпляров этого класса. По этой причине, когда вы insert элемент на self.my_list в любом случае A, он отображается во всех экземплярах A - все они имеют один и тот же список.

Чтобы создать атрибут экземпляра, вы должны установить self.some_attribute вместо установки some_attribute в области видимости класса. Во втором примере вы переустанавливаете self.my_list в новый объект списка в __init__, поэтому my_list больше не ссылается на атрибут класса. Он специфичен для этого экземпляра.

Ваше решение верно. Чтобы избежать путаницы, лучше не использовать одно и то же имя для атрибутов класса и экземпляра. Например:

class A(object): 

    default_list = [1, 2, 3, 4, 5] 

    def __init__(self, first): 
     self.my_list = self.reorder_list(first) 

    def reorder_list(self, first): 
     my_copy = copy.copy(self.default_list) 
     # ... do reordering on my_copy ... 
     return my_copy 
+0

Хорошо, спасибо! Я не понял, что это был * тот же * список для всех экземпляров. Я думал, что копия уже создана. И хороший совет для выбора другого имени для списка по умолчанию. – RvL

1

Это связано с областью действия my_list внутри класса. Как определено, my_list - это атрибут уровня класса. Таким образом, он может быть доступен через A.my_list или a.my_list после первого экземпляра. Так как побочный эффект начального изменения A.my_list был изменен на то, что когда-либо устанавливал последний экземпляр. Копия работает, потому что новый список создается и инициализируется значениями из атрибута уровня класса и используется вместо него.

>>> A.my_list 
[1, 2, 3, 4, 5] 
>>> a = A(4) 
>>> a.my_list 
[4, 2, 1, 5, 3] 
>>> A.my_list 
[4, 2, 1, 5, 3] 
0

Для того, чтобы он работал, как вы espected вы могли бы сделать и что-то вроде этого:

class A(object): 

my_list = [] 

def __init__(self, first): 
    self.my_list = [1, 2, 3, 4, 5] 
    self.reorder_list(first) 

def reorder_list(self, first): 

    self.my_list.insert(
     0, 
     self.my_list.pop(
       self.my_list.index(first) 
     ) 
    ) 
Смежные вопросы