2009-10-26 3 views
1

Я хочу создать пользовательский набор, который автоматически преобразует объекты в другую форму для хранения в наборе (см. Using a Python Dictionary as a key non-nested) для фона.Переопределение методов набора в Python

Если я переопределить add, remove, __contains__, __str__, update, __iter__, будет, что будет достаточно, чтобы другие операции ведут себя должным образом, или мне нужно переопределить что-нибудь еще?

+0

@Casebash: Пожалуйста, не комментируют свой вопрос , Даже «хорошее предложение» - в конечном счете - довольно глупо. Другие люди хотят ваш * вопрос * и выбранный * ответ * без большого количества пушистых вещей. –

ответ

7

Работа от абстрактных классов collections «s, так как @ kaizer.se предполагает, является оптимальным решением в 2.6 (не конечно, почему вы хотите назвать супер - какую функциональность вы пытаетесь делегировать, что лучше всего сделать путем сдерживания, а не наследования ?!).

Это правда, что вы не получаете update - предоставляя абстрактные методы, вы получаете __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, and isdisjoint (от collections.Set) плюс clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__ (от collections.MutableSet), что гораздо больше, чем вы получите от подклассов set (где вам придется переопределить каждый интересующий нас метод). Вам просто нужно предоставить другие методы набора, которые вы хотите.

Обратите внимание, что абстрактные базовые классы, такие как collections.Set являются довольно разными зверьми из конкретных классов, в том числе встроенных команд, такие как set и (в 2,6) хорошего старые sets.Set, одобряются, но по-прежнему вокруг (удалено в Python 3). ABC предназначены для наследования (и могут затем синтезировать некоторые методы у вас, как только вы реализуете все абстрактные методы, как вы должны) и, во-вторых, «регистрировать» классы, чтобы они выглядели так, как будто они унаследовали от них, даже если они не (сделать isinstance более полезным и полезным).

Вот рабочий пример для Python 3.1 и 2.6 (без уважительной причины использовать 3.0, а 3.1 только имеет преимущества по сравнению с ней, никаких недостатков):

import collections 

class LowercasingSet(collections.MutableSet): 
    def __init__(self, initvalue=()): 
    self._theset = set() 
    for x in initvalue: self.add(x) 
    def add(self, item): 
    self._theset.add(item.lower()) 
    def discard(self, item): 
    self._theset.discard(item.lower()) 
    def __iter__(self): 
    return iter(self._theset) 
    def __len__(self): 
    return len(self._theset) 
    def __contains__(self, item): 
    try: 
     return item.lower() in self._theset 
    except AttributeError: 
     return False 
+2

Его можно обобщить с помощью 'key (item)' вместо 'item.lower()' везде -> 'KeySet (« Aa », key = operator.methodcaller ('lower'))'. – jfs

+0

Почему вы подклассы из 'Set', а не' MutableSet'? Кто-нибудь, кроме меня, думает, что это очень запутанно, что модуль коллекций представляет собой смесь «реальных» коллекций (deque) и ABCs? – u0b34a0f6ae

+0

Стоит отметить, что 'Set' - это не то же самое, что' set' – Casebash

1

В Python 2.6:

import collections 
print collections.MutableSet.__abstractmethods__ 
# prints: 
# frozenset(['discard', 'add', '__iter__', '__len__', '__contains__']) 

подкласс collections.MutableSet и переопределить методы в приведенном выше списке.

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

def update(self, iterable): 
    for x in iterable: 
     self.add(x) 
+0

Когда я это делаю, я не получаю метод обновления – Casebash

+0

Плюс Я не могу назвать супер (используя Python 3.0) – Casebash

+1

@Casebash: Пожалуйста, включите в вопрос информацию Python 3.0, а не комментарий к ответу. –

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