2010-10-15 5 views
17

Я недавно перешел к проблеме кодирования, которую я имел, и кто-то, смотрящий на код, сказал, что список подклассов был плохим (моя проблема не была связана с этим классом). Он сказал, что вы не должны этого делать, и что он пришел с кучей плохих побочных эффектов. Это правда?Что следует учитывать перед списком подклассов?

Я спрашиваю, является ли список, как правило, неправильным для подкласса, и если да, то в чем причины. В качестве альтернативы, что я должен рассмотреть перед списком подклассов в Python?

+2

Список подклассов не является по своей сути плохим, но есть много случаев, когда это действительно не то, что вы хотите сделать. Мы не можем ответить, так ли это, если вы не дадите нам специфику. –

ответ

17

Нет никаких преимуществ для подкласса list. Ни один из методов не будет использовать какие-либо методы, которые вы переопределите, так что вы можете иметь неожиданные ошибки. Кроме того, очень часто путают такие вещи, как self.append вместо self.foos.append или особенно self[4], а не self.foos[4] для доступа к вашим данным. Вы можете сделать что-то, что работает точно так же, как список или (лучше) Однако очень понравился список, который вы действительно хотите, а просто подклассифицируете object.

+3

Что делать, если мы хотим добавить атрибут в список? Предположим, например, что mylist = []. Мы хотим что-то вроде mylist.x = 3. – riza

+1

@Selinap. В случае, когда я хотел, чтобы мое состояние включало список чего-то и int, я все же, вероятно, использовал бы композицию. Использование наследования для этого открывает путаницу в письменной форме, путаницу в использовании и на самом деле ничего не дает вам. –

+2

Это, похоже, неверно из python 3. Они содержат ['collections.UserList'] (https://docs.python.org/3.4/library/collections.html#collections.UserList) явно для этой цели. Он даже предполагает, что теперь возможно подклассирование из списка: «Потребность в этом классе была частично вытеснена возможностью подкласса непосредственно из списка»; (Я понимаю, что это старая тема, и комментарии выше, вероятно, были правдивыми во время написания, просто хочу сделать это понятным для людей, которые сейчас находят этот вопрос) – Claude

11

Я думаю, что первым вопросом, который я задал себе, является: «Является ли мой новый объект действительно списком?». Он идет, как список, говорит, как список? Или это что-то еще?

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

Если стандартные методы списка не имеют смысла, то ваш объект должен содержать список, а не список.

В старых списках подкатегорий python (2.2?) Была плохая идея по различным техническим причинам, но в современном python это нормально.

+4

+1 Только наследуйте, когда он действительно делает 100% -ный смысл, иначе сочините. – delnan

+0

Что касается побочных эффектов, он был немного устаревшим? Данные содержатся в списке, но есть множество других специальных методов, которые мне нужно перевернуть сверху, чтобы сделать несколько вещей. –

+0

Да, наследуйте отношения «is-a», составляйте почти все остальное. –

6

Ник правильный. Кроме того, пока я не могу говорить с Python, в других языках OO (Java, Smalltalk) подклассификация списка - плохая идея. Следует избегать наследования в целом и вместо этого использовать состав делегаций.

Скорее вы создаете класс контейнера и делегируете вызовы в список. Класс контейнера имеет ссылку на список, и вы можете даже разоблачить вызовы и возвраты списка в своих собственных методах. Это добавляет гибкости и позволяет вам изменить реализацию (другой тип списка или структуру данных) позже без нарушения любого кода. Если вы хотите, чтобы ваш список выполнял разные вещи типа listy, ваш контейнер может это сделать и использовать простой список как простую структуру данных. Представьте, если у вас было 47 различных видов использования списков. Вы действительно хотите поддерживать 47 различных подклассов? Вместо этого вы можете сделать это через контейнер и интерфейсы. Один класс для поддержки и позволяет людям называть ваши новые и улучшенные методы с помощью интерфейса (интерфейсов), при этом реализация остается скрытой.

17

abstract base classes, указанный в модуле collections, в частности MutableSequence, может быть полезен при реализации классов, подобных спискам. Они доступны в Python 2.6 и более поздних версиях.

С помощью ABC вы можете реализовать «базовые» функциональные возможности своего класса и предоставить методы, логически зависящие от того, что вы определили.

Например, реализация __getitem__ в collections.Sequence -derived класса будет достаточно, чтобы обеспечить ваш класс с __contains__, __iter__ и другими методами.

Возможно, вы захотите использовать объект списка, который будет использоваться для тяжелого подъема.

+1

С Python 3.3+ он был перемещен в модуль ['collections.abc'] (https://docs.python.org/3/library/collections.abc.html). – xmedeko

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