Chcę napisać niestandardową klasę, która zachowuje się dict
tak, jak - więc dziedziczę z dict
.
Moje pytanie brzmi jednak: czy muszę utworzyć członka prywatnego dict
w mojej __init__()
metodzie ?. Nie widzę w tym sensu, ponieważ mam już dict
zachowanie, jeśli po prostu odziedziczę po dict
.
Czy ktoś może wskazać, dlaczego większość fragmentów dziedziczenia wygląda tak, jak ten poniżej?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Zamiast prostszego ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
Właściwie myślę, że podejrzewam, że odpowiedź na to pytanie jest taka, że użytkownicy nie mogą uzyskać bezpośredniego dostępu do Twojego słownika (tj. Muszą korzystać z podanych przez Ciebie metod dostępu).
A co z operatorem dostępu do tablicy []
? Jak można to zaimplementować? Jak dotąd nie widziałem przykładu pokazującego, jak przesłonić []
operator.
Więc jeśli []
w klasie niestandardowej nie ma funkcji dostępu, dziedziczone metody bazowe będą działać na innym słowniku?
Wypróbowałem następujący fragment kodu, aby sprawdzić, czy rozumiem dziedziczenie w Pythonie:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(self, id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
print md[id]
Otrzymałem następujący błąd:
KeyError: <ID funkcji wbudowanej>
Co jest nie tak z powyższym kodem?
Jak poprawić klasę, myDict
aby móc pisać taki kod?
md = myDict()
md['id'] = 123
[Edytować]
Zedytowałem powyższy przykładowy kod, aby pozbyć się głupiego błędu, który popełniłem, zanim odskoczyłem od biurka. To była literówka (powinienem to zauważyć w komunikacie o błędzie).
źródło
dict
, powinieneś użyć samego obiektu (używającsuper
) zamiast po prostu delegować do instancji__dict__
- co zasadniczo oznacza, że tworzysz dwie dykty dla każdej instancji._dict__
atrybut zawierający wszystkie atrybuty obiektu (metody, pola itp.). Zdajesz nie chcą poeksperymentować z tego, chyba że chcesz napisać kod, który modyfikuje się ...Lubię to
Teraz możesz korzystać z wbudowanych funkcji, takich jak
dict.get()
asself.get()
.Nie musisz zawijać ukrytego
self._dict
. Twoja klasa to już dykt.źródło
dict
bez uprzedniego wywołania konstruktora.dict
rzeczywistości zawiera 2 instancje dyktowania: pierwszy to odziedziczony kontener, a drugi to dykt przechowujący atrybuty klasy - możesz tego uniknąć, używając slotów .__dict__
rzeczywistości jest on tworzony tylko przy pierwszym dostępie, więc jeśli użytkownicy nie próbują go używać, jest w porządku.__slots__
byłoby jednak miło.W trosce o kompletność, oto link do dokumentacji wspomnianej przez @ björn-pollex dla najnowszego Pythona 2.x (2.7.7 w momencie pisania):
Emulowanie typów kontenerów
(Przepraszam, że nie używam funkcji komentarzy, po prostu nie mogę tego robić przez stackoverflow.)
źródło
Problem z tym fragmentem kodu:
... polega na tym, że metoda 'add' (... i każda metoda, która ma być członkiem klasy) musi mieć zadeklarowane jawne 'self' jako pierwszy argument, na przykład:
Aby zaimplementować przeciążenie operatora w celu uzyskania dostępu do elementów za pomocą klucza, poszukaj w dokumentacji metod magicznych
__getitem__
i__setitem__
.Zauważ, że ponieważ Python używa Duck Typing, w rzeczywistości może nie być powodu, aby wyprowadzać twoją niestandardową klasę dict z klasy dict języka - nie wiedząc więcej o tym, co próbujesz zrobić (np. Jeśli musisz przekazać instancję this w jakimś kodzie, który się zepsuje, chyba że
isinstance(MyDict(), dict) == True
), może lepiej będzie po prostu zaimplementować API, które sprawi, że Twoja klasa będzie wystarczająco podobna do dyktowania, i zatrzymaj się na tym.źródło
Oto alternatywne rozwiązanie:
źródło
Naprawdę nie widzę nigdzie właściwej odpowiedzi na to pytanie
Jedyne, co naprawdę musisz zrobić, to zdefiniować własne
__init__
- to naprawdę wszystko, co jest.Inny przykład (trochę bardziej złożony):
Ten ostatni przykład jest przydatny, gdy chcesz osadzić jakąś logikę.
W każdym razie ... w skrócie
class GiveYourClassAName(dict)
wystarczy, aby twoja klasa zachowywała się jak dyktando. Każda operacja dyktowania, którą wykonujesz,self
będzie taka sama jak zwykły dykt.źródło
To jest moje najlepsze rozwiązanie. Używałem tego wiele razy.
Możesz użyć takich jak:
źródło
Nigdy nie dziedzicz z wbudowanego w Pythona dyktu! na przykład
update
metoda nie była używana__setitem__
, robią dużo dla optymalizacji. Użyj UserDict.źródło