speciali - self python




Sovrascrivere i metodi set in Python (2)

Voglio creare un set personalizzato che convertirà automaticamente gli oggetti in una forma diversa per la memorizzazione nel set (vedi Utilizzo di un dizionario Python come chiave non annidata ) per lo sfondo.

Se sostituisco add , remove , __contains__ , __str__ , update , __iter__ , sarà sufficiente per far sì che le altre operazioni si comportino correttamente o devo sovrascrivere qualcos'altro?


In Python 2.6:

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

sottoclasse collections.MutableSet e sovrascrive i metodi nell'elenco precedente.

il metodo di aggiornamento stesso è molto semplice, dato che viene implementato il minimo precedente

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

Lavorare dalle classi astratte delle collections , come suggerisce @ kaizer.se, è la soluzione appropriata in 2.6 (non è sicuro il motivo per cui si desidera chiamare super - quale funzionalità si sta tentando di delegare che non può essere gestita al meglio dal contenimento piuttosto che dall'ereditarietà ?!).

È vero che non si ottiene l' update : fornendo i metodi astratti, si ottengono __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, and isdisjoint (da collections.Set ) più clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__ (from collections.MutableSet ), che è molto più di quello che clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__ dal set sottoclassi (dove dovresti sovrascrivere ogni metodo di interesse). Dovrai solo fornire altri metodi che desideri.

Si noti che le classi astratte di base come le collections.Set Sono una bestia piuttosto diversa dalle classi concrete, compresi i builtin come set e (in 2.6) i vecchi vecchi sets.Set , deprecati ma ancora in circolazione (rimossi in Python 3). Gli ABC devono ereditare da (e possono quindi sintetizzare alcuni metodi da te una volta implementati tutti i metodi astratti, come devi) e secondariamente per "registrare" le classi con così sembrano come se li ereditassero anche quando non lo fanno (per rendere più utile e utile).

Ecco un esempio funzionante per Python 3.1 e 2.6 (nessuna buona ragione per usare 3.0, poiché 3.1 ha solo vantaggi su di esso, nessun svantaggio):

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




set