Por ejemplo, supongamos que quiero subclase dict
y tener todas las claves en mayúscula:
class capdict(dict):
def __init__(self,*args,**kwds):
super().__init__(*args,**kwds)
mod = [(k.capitalize(),v) for k,v in super().items()]
super().clear()
super().update(mod)
def __getitem__(self,key):
return super().__getitem__(key.capitalize())
def __setitem__(self,key,value):
super().__setitem__(key.capitalize(),value)
def __delitem__(self,key):
super().__detitem__(key.capitalize())
Esto funciona hasta cierto punto,
>>> ex = capdict(map(reversed,enumerate("abc")))
>>> ex
{'A': 0, 'B': 1, 'C': 2}
>>> ex['a']
0
pero, por supuesto, solo para los métodos que recordé implementar, por ejemplo
>>> 'a' in ex
False
No es el comportamiento deseado.
Ahora, la forma perezosa de completar todos los métodos que se pueden derivar de los "básicos" se estaría mezclando collections.abc.MutableMapping
. Solo que no funciona aquí. Supongo que los métodos en cuestión ( __contains__
en el ejemplo) ya los proporciona dict
.
¿Hay alguna manera de tener mi pastel y comerlo? ¿Alguna magia para dejar MutableMapping
ver solo los métodos que he anulado para que reimplemente los otros basados en esos?
python
python-3.x
Paul Panzer
fuente
fuente
MutableMapping
. Ver Diccionario insensible a mayúsculas y minúsculas .os._Environ
.Respuestas:
Lo que puedes hacer:
Esto probablemente no funcionará bien (es decir, no es el diseño más limpio), pero podría heredar de MutableMapping primero y luego de dict segundo.
Entonces MutableMapping usaría cualquier método que haya implementado (porque son los primeros en la cadena de búsqueda):
Mejor manera:
El enfoque más limpio (fácil de entender y probar) es simplemente heredar de MutableMapping y luego implementar los métodos requeridos usando un dict regular como el almacén de datos base (con composición en lugar de herencia):
fuente
super
explícitosdict
, parece funcionar, excepto laslen
devoluciones0
. ¿De dónde viene eso?(D, MutableMapping, dict)
. Ese es el método MutableMappiing .__ len __ () que siempre devuelve 0. No se debe llamar directamente; siempre se supone que debe anularse. Por eso tienes que llamardict.__len__(self)
directamente. Y esa es una de las razones por las que dije "esto probablemente no funcionará bien" ;-)