2016-12-07 2 views
0

Я написал сценарий, который решает проблемы судоку. Для моделирования каждого слота сетки, у меня в определенном слоте первый раза и классах Грида, как это (полный код elipsed для простоты:Индекс списка подкласса объекта в родительский список

class Slot(): 
    def __init__(self,grid): 
     self.grid = grid 
     self.values = list(range(9)) 

    def pos(self): 
     return self.grid.index(self) 

class Grid(list): 
    def __init__(self): 
     for i in range(9*9): 
      self.append(Slot(self)) 

Как это, я могу определить метод для моего класса Slot используя self.pos() и self.values ​​(), например:.

g = Grid() 
g[5].pos() -> returns 5, OK ! 

Теперь, когда мой полный скрипт работает просто отлично, я хочу, чтобы реорганизовать его, и, как слот в основном списке, принадлежащих к Grid, я решил, что это будет здорово для моего списка Slot для подкласса, например:

class Slot(list): 
    def __init__(self,grid): 
     self.grid = grid 
     self.append(list(range(9))) 

    def pos(self): 
     return self.grid.index(self) 

class Grid(list): 
    def __init__(self): 
     for i in range(9*9): 
      self.append(Slot(self)) 

g = Grid() 
g.index(g[5]) -> returns 0, KO ! 

Я попытался сначала запустить список, т. Е. Super(). INIT (список (диапазон (9)), а также несколько вариантов, но ничего не похоже на работу Что я упускаю

PS:.? g.index(g[5]) просто описать, я знаю, что это бессмысленно. Я использую эту логику в методах внутри своих объектов (self.pos() и т.д.)

+0

Почему бы не использовать композицию над наследованием, иметь список как внутренний атрибут и просто показать, что все соответствующие методы для протокола протокола работают нормально? (такие атрибуты, как '__getitem__',' __len__' и т. д.) –

+0

Ни один из классов не должен расширять «список». Это детализация реализации, а не ограничение модели. Вы должны скрывать реализацию и использовать композицию; на самом деле я бы не использовал 'list' в любом классе, особенно в' Slot', где 'index (x) == x'! –

+0

Ну, чтобы избежать этого, я пытаюсь подкласса, Мои методы в основном используются в объекте Slot (например: первая версия, я делаю self.values.remove (x), я думал о делать self.remove (x) и т. д.) Переопределить __getitem__ и т. д. было бы излишним, (ответ на вопрос Lukasz) –

ответ

1

делая Slot подкласс list вы также сделать сравнение между Slot случаях использовать логику, определенную для list с (так как вы не отменены).

Поскольку все Slot s содержат s AME значение:

self.append(list(range(9))) 

g.index() просто соответствует первой записи по grid получая 0 в качестве результата.

Когда вы унаследовали от object (как в вашем первом примере Slot), все экземпляры сравнивались неравномерно с самим собой, как определено в справочнике Python (если не реализована логика, которая диктует иначе).

Короче говоря, вам нужно будет переопределить методы сравнения, если вам нужны слоты с похожими элементами, которые будут обрабатываться по-разному при сравнении. В дополнение к этому, вы можете захотеть пересмотреть подкласс из list и вместо этого выбрать UserList от collections.

+0

Спасибо за это объяснение, это именно то, что я искал.Каким будет ваш совет, чтобы мой код был как можно более «pythonic» ;-) Сохраняя мою первую реализацию или переопределяя логику сравнения? –

+1

@ Lapin-Blanc Если 'Slot's * требуется *, чтобы вести себя как списки, то подкласс для« списка »имеет смысл для меня (хотя состав, как утверждают другие, может быть менее грязной альтернативой). Если вы придерживаетесь подкласса, я бы предположил, что вы наследуем его из 'collections.UserList', хотя, поскольку в этих сценариях он лучше себя ведет. Я бы просто пересмотрел сравнения, чтобы вести себя так, как мне было нужно. –

+0

Спасибо! Мне нравится список подкласса, так как мой алгоритм основан на удалении возможных значений из объекта слотов, пока остается только одно значение, которое является окончательным для решения. Кстати, что вы подразумеваете под «это ведет себя лучше», если я могу спросить далее ... –

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