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

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

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

Ответ 1

Работа с абстрактными классами collections, как предлагает @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

В Python 2.6:

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

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

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

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