Anulando los métodos establecidos en Python
-
06-07-2019 - |
Pregunta
Quiero crear un conjunto personalizado que convertirá automáticamente los objetos en una forma diferente para el almacenamiento en el conjunto (consulte Usar un diccionario de Python como clave no anidada ) para el fondo.
Si anulo add
, remove
, __contains__
, __str__
, update
, __iter__
, ¿será eso suficiente para hacer que las otras operaciones se comporten correctamente, o debo anular algo más?
Solución
Trabajar a partir de colecciones
, como sugiere @ kaizer.se, es la solución adecuada en 2.6 (no estoy seguro de por qué quiere llamar super - ¿qué funcionalidad está intentando delegar? ¿No se puede hacer mejor por contención en lugar de por herencia ?!).
Es cierto que no obtiene update
; al proporcionar los métodos abstractos, obtiene __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, e isdisjoint
(de collections.Set
) más clear, pop, remove, __ior__, __iand__, __ixor__, y __isub__
(de las colecciones de . MutableSet
), que es mucho más de lo que obtendría de la subclase set
(donde tendría que anular todos los métodos de interés). Solo tendrás que proporcionar otros métodos de configuración que desees.
Tenga en cuenta que las clases base abstractas como collections.Set
son una bestia bastante diferente de las clases concretas, incluidas las incorporadas como set
y (en 2.6) good old sets.Set
, en desuso pero todavía alrededor (eliminado en Python 3). Los ABC están destinados a heredar (y luego pueden sintetizar algunos métodos a partir de usted una vez que implemente todos los métodos abstractos, como debe) y, de forma secundaria, a " registrar " con las clases, por lo que parecen como si hubieran heredado de ellas incluso cuando no lo hacen (para hacer que isstance
sea más útil y útil).
Este es un ejemplo práctico de Python 3.1 y 2.6 (no es una buena razón para usar 3.0, ya que 3.1 solo tiene ventajas sobre él, no tiene desventaja):
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
Otros consejos
En Python 2.6:
import collections
print collections.MutableSet.__abstractmethods__
# prints:
# frozenset(['discard', 'add', '__iter__', '__len__', '__contains__'])
subclase collections.MutableSet
y reemplaza los métodos en la lista anterior.
el método de actualización en sí es muy fácil, dado que se implementó el mínimo anterior
def update(self, iterable):
for x in iterable:
self.add(x)