Załóżmy na przykład, że chcę podklasę dict
i mieć wszystkie klawisze wielkich liter:
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())
Działa to do pewnego stopnia,
>>> ex = capdict(map(reversed,enumerate("abc")))
>>> ex
{'A': 0, 'B': 1, 'C': 2}
>>> ex['a']
0
ale, oczywiście, tylko dla metod, które zapamiętałem na przykład
>>> 'a' in ex
False
nie jest pożądanym zachowaniem.
Teraz leniwy sposób wypełniania wszystkich metod, które można wyprowadzić z „rdzeniowych”, byłby wmieszany collections.abc.MutableMapping
. Tylko, że tutaj nie działa. Zakładam, że metody, o których mowa ( __contains__
w tym przykładzie) są już dostarczone przez dict
.
Czy istnieje sposób na zjedzenie mojego ciasta i zjedzenie go? Jakaś magia pozwalająca MutableMapping
zobaczyć tylko metody, które zastąpiłem, tak aby reimplementować inne w oparciu o te?
python
python-3.x
Paul Panzer
źródło
źródło
MutableMapping
. Zobacz słownik bez rozróżniania wielkości liter .os._Environ
.Odpowiedzi:
Co możesz zrobić:
To prawdopodobnie nie będzie działać dobrze (tzn nie najczystsze projekt), ale można dziedziczyć MutableMapping a potem z dict sekundę.
Następnie MutableMapping użyłby wszelkich zaimplementowanych metod (ponieważ są one pierwsze w łańcuchu wyszukiwania):
Lepszy sposób:
Najczystszym podejściem (łatwym do zrozumienia i przetestowania) jest po prostu odziedziczenie po MutableMapping, a następnie wdrożenie wymaganych metod przy użyciu zwykłego dykta jako podstawowego magazynu danych (z kompozycją zamiast dziedziczenia):
źródło
super
s na jawne,dict
wtedy wydaje się, że działa, z wyjątkiemlen
zwrotów0
. Skąd to pochodzi?(D, MutableMapping, dict)
. Jest to metoda MutableMappiing .__ len __ () , która zawsze zwraca 0. Nie była przeznaczona do bezpośredniego wywoływania - zawsze powinna być nadpisana. Dlatego musisz zadzwonićdict.__len__(self)
bezpośrednio. I to jest jeden z powodów, dla których powiedziałem: „to prawdopodobnie nie zadziała dobrze” ;-)