Переопределение методов набора в Python

Я хочу создать пользовательский набор, который будет автоматически преобразовывать объекты в другую форму для хранения в наборе (см. Использование словаря Python в качестве не вложенного ключа) для фона.

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

2 ответа

Решение

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

Это правда, что вы не получаете 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

В 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)
Другие вопросы по тегам