Possiamo pensare a OOP come modellare il comportamento di un sistema. Nota che il sistema non deve esistere nel "mondo reale", anche se le metafore del mondo reale a volte possono essere utili (ad esempio "condutture", "fabbriche", ecc.).
Se il nostro sistema desiderato è troppo complicato per modellare tutto in una volta, possiamo scomporlo in parti più piccole e modellare quelle (il "dominio del problema"), che potrebbe comportare una rottura ulteriore, e così via fino a quando non arriviamo a pezzi il cui comportamento corrisponde (più o meno) a quello di qualche oggetto linguaggio incorporato come un numero, una stringa, una lista, ecc.
Una volta che abbiamo questi semplici pezzi, possiamo combinarli insieme per descrivere il comportamento di pezzi più grandi, che possiamo combinare insieme in pezzi ancora più grandi, e così via fino a che non possiamo descrivere tutti i componenti del dominio che sono necessari per un intero sistema.
È questa fase di "combinazione" in cui potremmo scrivere alcune classi. Scriviamo classi quando non esiste un oggetto esistente che si comporta nel modo in cui vogliamo. Ad esempio, il nostro dominio potrebbe contenere "foos", raccolte di foos chiamate "barre" e raccolte di barre chiamate "baz". Potremmo notare che i foos sono abbastanza semplici da modellare con le stringhe, quindi lo facciamo. Troviamo che le barre richiedono che il loro contenuto obbedisca a qualche particolare vincolo che non corrisponde a qualcosa che Python fornisce, nel qual caso potremmo scrivere una nuova classe per far rispettare questo vincolo. Forse i baz non hanno tali peculiarità, quindi possiamo semplicemente rappresentarli con una lista.
Nota che potremmo scrivere una nuova classe per ognuno di questi componenti (foos, barre e baz), ma non bisogno di se c'è già qualcosa con il comportamento corretto. In particolare, affinché una classe sia utile deve "fornire" qualcosa (dati, metodi, costanti, sottoclassi, ecc.), Quindi anche se abbiamo molti livelli di classi personalizzate, dobbiamo usare infine alcune funzionalità integrate; per esempio, se scrivessimo una nuova classe per foos probabilmente conterrebbe solo una stringa, quindi perché non dimenticare la classe foo e la classe della barra contiene invece quelle stringhe? Tieni presente che le classi sono anche un oggetto incorporato, sono solo particolarmente flessibili.
Una volta ottenuto il nostro modello di dominio, possiamo prendere alcune istanze particolari di quei pezzi e organizzarli in una "simulazione" del particolare sistema che vogliamo modellare (ad esempio "un sistema di apprendimento automatico" per ... ").
Una volta che abbiamo questa simulazione, possiamo eseguirla e presto, abbiamo un sistema di apprendimento automatico (simulazione di a) per ... (o qualsiasi altra cosa stavamo modellando).
Ora, nella tua situazione particolare, stai cercando di modellare il comportamento di un componente "feature extractor". La domanda è: ci sono oggetti built-in che si comportano come un "feature extractor", o hai bisogno di suddividerlo in cose più semplici? Sembra che gli estrattori di feature si comportino in modo molto simile agli oggetti funzione, quindi penso che staresti bene a utilizzarli come modello.
Una cosa da tenere a mente quando si impara su questo tipo di concetti è che linguaggi diversi possono fornire diverse funzionalità e oggetti incorporati (e, naturalmente, alcuni non usano nemmeno termini come "oggetti"!). Quindi le soluzioni che hanno senso in una lingua potrebbero essere meno utili in un'altra (questo può anche applicarsi a versioni diverse della stessa lingua!).
Storicamente, un lotto della letteratura OOP (in particolare "schemi di progettazione") si è concentrato su Java, che è molto diverso da Python. Ad esempio, le classi Java non sono oggetti, Java non ha avuto oggetti funzione fino a poco tempo fa, Java ha un rigoroso controllo dei tipi (che incoraggia interfacce e sottoclassi) mentre Python incoraggia la tipizzazione anatra, Java non ha oggetti modulo, interi Java / galleggianti / etc. non sono oggetti, la meta-programmazione / introspezione in Java richiede "riflessione" e così via.
Non sto provando a scegliere su Java (come un altro esempio, molta teoria OOP ruota attorno a Smalltalk, che è ancora molto diversa da Python), sto solo cercando di far notare che dobbiamo pensare molto attentamente il contesto e i vincoli in cui sono state sviluppate le soluzioni e se questo corrisponde alla situazione in cui ci troviamo.
Nel tuo caso, un oggetto funzione sembra una buona scelta. Se ti stai chiedendo perché alcune linee guida sulle "migliori pratiche" non menzionino gli oggetti funzione come una possibile soluzione, potrebbe semplicemente essere perché quelle linee guida sono state scritte per vecchie versioni di Java!