Możemy myśleć o OOP jako o modelowaniu zachowania systemu. Zauważ, że system nie musi istnieć w „prawdziwym świecie”, chociaż metafory w świecie rzeczywistym mogą czasem być przydatne (np. „Rurociągi”, „fabryki” itp.).
Jeśli nasz pożądany system jest zbyt skomplikowany, aby modelować go od razu, możemy go rozbić na mniejsze części i modelować te („dziedzina problemowa”), co może wymagać dalszego podziału, i tak dalej, aż dojdziemy do kawałków, których zachowanie się zgadza (mniej więcej) dla niektórych wbudowanych obiektów językowych, takich jak liczba, ciąg znaków, lista itp.
Po uzyskaniu tych prostych elementów możemy połączyć je razem, aby opisać zachowanie większych elementów, które możemy połączyć razem w jeszcze większe kawałki i tak dalej, dopóki nie będziemy w stanie opisać wszystkich składników domeny, które są potrzebne dla całości system.
W tej fazie „łączenia się” możemy napisać niektóre klasy. Piszemy klasy, gdy nie ma istniejącego obiektu, który zachowuje się tak, jak chcemy. Na przykład nasza domena może zawierać „foos”, kolekcje foos zwane „batonami” i kolekcje batoników nazywanych „bazami”. Możemy zauważyć, że foos są wystarczająco proste do modelowania za pomocą łańcuchów, więc to robimy. Okazuje się, że paski wymagają, aby ich zawartość była zgodna z określonym ograniczeniem, które nie pasuje do niczego, co zapewnia Python, w takim przypadku możemy napisać nową klasę w celu wymuszenia tego ograniczenia. Być może bazy nie mają takich osobliwości, więc możemy po prostu przedstawić je za pomocą listy.
Zauważ, że moglibyśmy napisać nową klasę dla każdego z tych składników (foos, barów i baz), ale nie musimy, jeśli jest już coś z prawidłowym zachowaniem. W szczególności, aby klasa była użyteczna, musi „dostarczyć” coś (dane, metody, stałe, podklasy itp.), Więc nawet jeśli mamy wiele warstw klas niestandardowych, musimy w końcu użyć wbudowanej funkcji; na przykład, gdybyśmy napisali nową klasę dla foos, prawdopodobnie zawierałaby ona tylko ciąg znaków, więc dlaczego nie zapomnieć o klasie foo i pozwolić, aby klasa bar zawierała te łańcuchy zamiast tego? Pamiętaj, że klasy są również wbudowanym obiektem, są one szczególnie elastyczne.
Kiedy już mamy nasz model domeny, możemy wziąć pewne szczególne przykłady tych elementów i ustawić je w „symulacji” konkretnego systemu, który chcemy modelować (np. „System uczenia maszynowego dla ...”).
Kiedy już mamy tę symulację, możemy ją uruchomić i hej presto, mamy działający (symulacja) system uczenia maszynowego dla ... (lub cokolwiek, co modelowaliśmy).
Teraz, w twojej konkretnej sytuacji, próbujesz modelować zachowanie komponentu „ekstraktora funkcji”. Pytanie brzmi: czy są jakieś wbudowane obiekty, które zachowują się jak „ekstraktor funkcji”, czy może trzeba je rozbić na prostsze rzeczy? Wygląda na to, że ekstraktory funkcji zachowują się bardzo podobnie do obiektów funkcyjnych, więc myślę, że możesz użyć ich jako modelu.
Jedną z rzeczy, o których należy pamiętać, ucząc się o tego rodzaju pojęciach, jest to, że różne języki mogą zapewniać różne wbudowane funkcje i obiekty (i oczywiście niektóre nie używają nawet terminologii takiej jak „obiekty”!). Dlatego rozwiązania, które mają sens w jednym języku, mogą być mniej przydatne w innym (może to nawet dotyczyć różnych wersji tego samego języka!).
Historycznie wiele literatury dotyczącej OOP (szczególnie „wzorce projektowe”) koncentrowało się na Javie, która jest zupełnie inna niż Python. Na przykład klasy Java nie są obiektami, Java do niedawna nie miała obiektów funkcyjnych, Java ma ścisłe sprawdzanie typów (co zachęca do tworzenia interfejsów i podklas), podczas gdy Python zachęca do pisania kaczego, Java nie ma obiektów modułowych, liczb całkowitych Java / floats / etc. nie są obiektami, metaprogramowanie / introspekcja w Javie wymaga „refleksji” i tak dalej.
Nie próbuję wybierać na Javie (jako inny przykład, wiele teorii OOP obraca się wokół Smalltalk, który znowu bardzo różni się od Pythona), po prostu próbuję wskazać, że musimy bardzo uważnie przemyśleć kontekst i ograniczenia, w których opracowano rozwiązania, i czy pasuje to do sytuacji, w której się znajdujemy.
W twoim przypadku obiekt funkcji wydaje się dobrym wyborem. Jeśli zastanawiasz się, dlaczego niektóre wytyczne dotyczące najlepszych praktyk nie wspominają o obiektach funkcyjnych jako możliwym rozwiązaniu, być może dlatego, że te wytyczne zostały napisane dla starych wersji Java!