2014-01-17 5 views
2

Я хочу расширить функциональность класса «список» и добавить пользовательские обработчики для событий: «Добавить новый элемент в список» и «Удалить элемент из списка». Для этой задачи я не хочу использовать композицию, лучше наследование.Python: правильный способ расширения списка

Что я пытался сделать:

class ExtendedList(list): 

    def append(self, obj): 
     super(ExtendedList, self).append(obj) 
     print('Added new item') 

    def extend(self, collection): 
     if (hasattr(collection, '__iter__') or hasattr(collection, '__getitem__')) and len(collection)>0: 
      for item in collection: 
       self.append(item) 

    def insert(self, index, obj): 
     super(ExtendedList, self).insert(index, obj) 
     print('Added new item') 

    def remove(self, value): 
     super(ExtendedList, self).remove(value) 
     print('Item removed') 

Но это не работает правильно. Я не могу уловить все добавления и удаления событий. Например:

collection = ExtendedList() 
collection.append('First item') 
# Out: "Added new item\n"; collection now is: ['First item'] 
collection.extend(['Second item', 'Third item']) 
# Out: "Added new item\nAdded new item\n"; collection now is: ['First item', 'Second item', 'Third item'] 
collection += ['Four item'] 
# Don't out anythink; collection now is: ['First item', 'Second item', 'Third item', 'Four item'] 
collection.remove('First item') 
# Out: "Item removed\n"; collection now is: ['Second item', 'Third item', 'Four item'] 
del collection[0:2] 
# Don't out anythink; collection now is: ['Four item'] 
collection *= 3 
# Don't out anythink; collection now is: ['Four item', 'Four item', 'Four item'] 

Что такое правильный способ расширить класс «список» для моей ситуации? Спасибо за помощь.

+1

Здесь не стоит определять подкласс списка. Вместо этого вы должны поддерживать агрегацию над наследованием – gefei

+0

Каждый из них делает разные вещи, поэтому используйте тот, который более подходит для того, что вы пытаетесь выполнить? – brandonscript

+1

Вы показали, что происходит, но что с этим не так? Что вы хотите? – nmichaels

ответ

5

Вместо того, чтобы наследовать от list, наследовать от его базового базового класса, collections.MutableSequence. Это делает всю основную работу для вас, позволяя вам сосредоточиться на том, что вы хотите изменить. Есть хороший вопрос по ABC here.

1

Посмотрите на класс UserList: http://pydoc.org/2.2.3/UserList.html Он показывает все методы, которые вам нужно изменить. Проблема в том, что type(ExtendedList([]) * 2) == list.

+1

Это действительно устаревший ответ. У Python 2.2+ нет проблем с расширением 'list', у« проблемы »было решение с 2.3, а у 2.6+ есть [' MutableSequence'] (http://docs.python.org/2/library/collections.html # collections-abstract-base-classes) ABC, удалив последнюю причину, когда кто-либо снова посмотрит на «UserList», поэтому он устарел и полностью удалился из документов. – abarnert

+0

Справа. Сейчас он устарел. просто не мог вспомнить MutableSequence. – User

+0

Извините, он был удален в 3.0, а не 2.6. 2.6 переписывает его и [другие связанные устаревшие модули] (http://docs.python.org/2.6/library/userdict.html?highlight=userlist#module-UserList) на одну страницу, которая напоминает вам несколько предложений, которые " Примечание. Этот модуль доступен только для обратной совместимости. " Тем не менее, это не очень хорошее предложение. Особенно для OP, который выглядит так, как будто использует Python 3.x. – abarnert

3

Операции, такие как *=, += и del реализованы с использованием функций оператора в list класса как __add__, __delitem__, __delslice__ и т.д. Есть много из них. Если вы хотите перехватить все возможные вызовы в ваш расширенный класс списка, вам придется переопределить большинство, если не всех этих операторов.

Потому что у вас нет контроля над тем, как реализованы встроенные классы, обычно легче составить новый класс вокруг встроенных команд, чем в наследуют из встроенных команд.

+0

Кажется, я ошибаюсь и действительно лучше использовать агрегацию или унаследовать от MutableSequence ... – uzumaxy

2

Если вы хотите переопределить операторы типа +, вам нужно будет сделать это явно. The documentation поможет вам понять, что нужно изменить.

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