Oto dwojakie pytanie, z części teoretycznej i praktycznej:Dyktowanie podklasowe: powinno się nazywać .__ init __()?
Kiedy rozszerzasz DICT:
class ImageDB(dict):
def __init__(self, directory):
dict.__init__(self) # Necessary??
...
powinien dict.__init__(self)
nazwać, po prostu jako „bezpieczeństwa” środka (na przykład w przypadku, są pewne nietrywialne szczegóły dotyczące implementacji, które mają znaczenie)? czy istnieje ryzyko, że kod zerwie z przyszłą wersją Pythona, jeśli zostanie wywołana dict.__init__()
, a nie , a nie? Szukam podstawowego powodu robienia jednej rzeczy lub drugiej, tutaj (praktycznie, wywołanie dict.__init__()
jest bezpieczne).
Domyślam się, że kiedy jest wywoływane ImageDB.__init__(self, directory)
, self jest już nowym pustym obiektem dict, a zatem nie ma potrzeby wywoływania dict.__init__
(chcę, aby dyktatura była pusta, na początku). Czy to jest poprawne?
Edit:
Im bardziej praktyczne pytanie za fundamentalne pytanie powyższego jest następujący. Myślałem o podklasowaniu dict, ponieważ często używałbym składni db [...] (zamiast robić db.contents [...] cały czas); jedyne dane obiektu (atrybut) jest rzeczywiście naprawdę dyktować. Chcę dodać kilka metod do bazy danych (na przykład get_image_by_name()
, lub get_image_by_code()
, na przykład) i tylko przesłonić __init__()
, ponieważ baza danych obrazu jest zdefiniowany przez katalog, który go zawiera.
Podsumowując, The (praktyczne) pytanie mogłoby być: co jest dobre, realizacja czegoś, co zachowuje się jak słownik, chyba że jej inicjalizacji jest inny (to zajmie tylko nazwę katalogu), oraz że posiada dodatkowy metody?
"Fakty" zostały wymienione w wielu odpowiedziach. Więc domyślam się, że wszystko sprowadza się do: czy podklasujesz dict, zastępujesz __init__()
i dodajesz metody, czy też piszesz funkcję (fabryczną), która zwraca dict, do którego dodajesz metody? Jestem skłonny preferować pierwsze rozwiązanie, ponieważ funkcja fabryka zwraca obiekt, którego typ nie wskazuje, że ma on dodatkową semantykę i metody, ale co o tym myślisz?
Edycja 2:
wnoszę z odpowiedzią każdego człowieka, że nie jest to dobry pomysł, aby podklasy dict gdy nowa klasa „nie jest słownik”, aw szczególności, gdy jego metoda __init__
nie może samo argumenty jako dict's __init__
(co ma miejsce w "pytaniu praktycznym" powyżej). Innymi słowy, jeśli dobrze rozumiem, konsensus wydaje się być następujący: podczas podklasy wszystkie metody (w tym inicjalizacja) muszą mieć ten sam podpis co metody klasy bazowej. Dzięki temu isinstance (subclass_instance, dict) gwarantuje, że można na przykład użyć subclass_instance.__init__()
, np. dict.__init__()
.
Pojawia się kolejne praktyczne pytanie: w jaki sposób powinna zostać wdrożona klasa, która jest podobna do metody dyktowania, z wyjątkiem metody inicjowania? bez podklasy? to wymagałoby jakiegoś uciążliwego kodu, nie?
Funkcja fabryczna jest drogą do zrobienia. Jeśli chcesz dostosować zachowanie * instancji *, możesz utworzyć podklasę. Jeśli chcesz tylko nadpisać * inicjalizację * nie musisz niczego podklasować, ponieważ twoje instancje nie różnią się od standardowych. Pamiętaj, że __init__ nie jest częścią interfejsu instancji, ale klasy. –
O ile widzę to dla tego problemu byłoby najlepiej dodać metodę "__getitem__" do ImageDB zamiast podklasy dyktować, ponieważ to _nie_ dykt. To pozwala ci robić to, co chcesz, bez użycia wszystkich takich metod jak 'pop()', które wydają się nieodpowiednie dla twojej klasy. –
@gs: Dobra uwaga, o pop; rzeczywiście jest to, przynajmniej na razie, nieistotne (zawartość bazy danych jest zdefiniowana tylko podczas inicjalizacji). Uważam, że najlepiej jest, jeśli implementacja ściśle pasuje do niezbędnych funkcji. – EOL