Substituindo métodos definidos em Python
-
06-07-2019 - |
Pergunta
Eu quero criar um conjunto personalizado que irá converter automaticamente objetos em uma forma diferente para armazenamento no conjunto (ver Usando um dicionário Python como uma chave não aninhado) para o fundo.
Se eu substituir add
, remove
, __contains__
, __str__
, update
, __iter__
, será isso suficiente para fazer as outras operações comportar corretamente, ou que eu preciso para substituir qualquer outra coisa?
Solução
Trabalho de classes abstratas de collections
, como @ kaizer.se sugere, é a solução adequada em 2,6 (não sei por que você quer chamar de super - o que a funcionalidade que você está tentando delegar que não pode o melhor feito por contenção em vez de herança?!).
É verdade que você não obter update
- fornecendo os métodos abstratos, você começa __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, and isdisjoint
(de collections.Set
) mais clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__
(de collections.MutableSet
), que é muito mais do que você deseja obter a partir subclasse set
(onde você 'teria que substituir todas método de juros). Você só terá que fornecer outros métodos set que você deseja.
Note que as classes base abstratas como collections.Set
são um animal muito diferente de classes concretas, incluindo builtins como set
e (em 2.6) boa sets.Set
velha, obsoleta, mas ainda em torno de (removido em Python 3). ABCs são destinados a herdar a partir de (e pode, então, sintetizar alguns métodos de você uma vez que você implementar todos os métodos abstratos, como você deve) e, secundariamente, para "registrar" as classes com que eles olham como se eles herdaram a partir deles, mesmo quando não o fazem (para fazer isinstance
mais utilizável e útil).
Aqui está um exemplo de trabalho para Python 3.1 e 2.6 (sem boa razão para usar 3.0, como 3.1 só tem vantagens sobre ele, nenhuma desvantagem):
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
Outras dicas
Em Python 2.6:
import collections
print collections.MutableSet.__abstractmethods__
# prints:
# frozenset(['discard', 'add', '__iter__', '__len__', '__contains__'])
subclasse collections.MutableSet
e substituir os métodos na lista acima.
o próprio método de atualização é muito fácil, uma vez que o mínimo acima é implementado
def update(self, iterable):
for x in iterable:
self.add(x)