Pratique de l'héritage de classe en python comme vu dans sklearn

introduction

Comment écrire l'héritage de classe en Python? J'écrirai une édition pratique sur. Il n'y a pas d'édition de base.

Quand est-ce important?

Cela semble utile lors de la création de logiciels et de bibliothèques à grande échelle. Si vous écrivez une méthode qui est définie de la même manière dans plusieurs classes de la classe abstraite ou de la classe parente qui sert de modèle, vous n'avez pas besoin de la définir dans la classe enfant.

Cette fois, prenons comme exemple le TransformerMixin de scikit-learn, que tout le monde adore. TransformerMixin est une classe utilisée partout dans scikit-learn. Dans scikit-learn, «fit» et «transform» sont souvent utilisés pour le prétraitement, etc., et «fit_transform» qui les exécute ensemble est implémenté dans «Transformer Mixin».

Ce mécanisme est un exemple très simple que fit_transform peut être utilisé simplement en héritant.

Pour référence, python implémente généralement une classe abstraite qui hérite de ʻabc.ABCMeta`. Il existe un package appelé abc qui est toujours disponible en Python et est utilisé pour définir des classes abstraites. Voir aussi les références à la fin de cet article.

abc — Abstract Base Classes

Ce que j'ai essayé

J'ai essayé les deux points suivants. J'écrirai.

  1. Lecture du code source
  2. Déplacement de l'exemple de code

Lecture du code source

Lisons d'abord le code ci-dessous. Il est tiré de la page github de scikit-learn. scikit-learn TransformerMixin

base.py


...
class TransformerMixin:
    def fit_transform(self, X, y=None, **fit_params):
        ...
        if y is None:
        ...
            return self.fit(X, **fit_params).transform(X)
        else:
        ...
            return self.fit(X, y, **fit_params).transform(X)
...

Lors de la définition d'une classe abstraite en Python, une classe appelée ʻabc.ABCMeta est souvent utilisée. Cependant, dans l'exemple ci-dessus, seule la méthode est définie sans utiliser ʻabc.ABCMeta.

«Les classes abstraites qui utilisent abc.ABCMeta» et «@ abc.abstractmethod» peuvent être héritées pour créer des classes qui forcent l'implémentation. D'un autre côté, avec TransformerMixin ci-dessus, nous voulons simplement rendre les méthodes communes disponibles pour toutes les destinations d'héritage. Dans ce cas, vous n'avez pas besoin d'utiliser ʻabc`.

Exemple de code déplacé

J'essaierai d'écrire. Si vous utilisez une classe abstraite qui utilise ʻabc`, cela fonctionne comme suit. De plus, ne vous inquiétez pas car le nom de la fonction etc. est Abekobe ...

$ cat sampleAbsclass.py
from abc import ABCMeta, abstractmethod
class DensityMixin(metaclass=ABCMeta):
    @abstractmethod
    def score(self, X, y=None):
        pass

class OneClassSvm(DensityMixin):
    def __init__(self):
        print('echo echo', 'hello hello')
    # def score(self, X, y=None):
    #     print(*X.shape)

def main():
    ocsvm = OneClassSvm()
    from numpy.random import randn
    X=randn(100, 10)
    ocsvm.score(X)
    return 0

if __name__=='__main__':
    main()
$ python sampleAbsclass.py
Traceback (most recent call last):
  File "sampleAbsclass.py", line 21, in <module>
    main()
  File "sampleAbsclass.py", line 14, in main
    ocsvm = OneClassSvm()
TypeError: Can't instantiate abstract class OneClassSvm with abstract methods score

Il existe une méthode score avec un décorateur @ abstractmethod dans le DensityMixin de la classe abstraite, mais elle n'est pas implémentée dans le ʻOneClassSvm` ** Keshikaran hérité! Le message d'erreur est **.

Si vous décommentez la fonction de partition de ʻOneClassSvm`, cela fonctionne comme ci-dessous.

$ python sampleAbsclass.py
echo echo hello hello
100 10

Autres: Précautions lors de l'utilisation de abc.ABCMeta

Une autre mise en garde qui apparaît lorsque vous utilisez beaucoup ʻabc.ABCMeta est lorsque la classe A hérite de plusieurs classes abstraites. "Si même une classe A a une classe abstraite qui hérite de ʻabc.ABCMeta, alors les autres classes héritées doivent également hériter de ʻabc.ABCMeta`." Il y a un point. Si vous interrompez cela, vous recevrez le message d'erreur suivant.

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Cela se produit également dans d'autres langues, donc je pense que c'est pratique de le faire. Vous devriez apprendre la théorie du langage de programmation correctement ...

Autre 2 Exemple utilisant abc.ABCMeta

Il existe une implémentation de scikit-learn qui utilise ʻabc.ABCMeta, alors jetons un œil là aussi. Ce qui suit est extrait de [_PLS --scikit-learn](https://github.com/scikit-learn/scikit-learn/blob/1495f69242646d239d89a5713982946b8ffcf9d9/sklearn/cross_decomposition/pls_.py#L120). Vous pouvez voir que @ abstractmethod est ajouté uniquement à la méthode __init __`.

pls_.py


from abc import ABCMeta, abstractmethod
...
class _PLS(BaseEstimator, TransformerMixin, RegressorMixin, MultiOutputMixin,
           metaclass=ABCMeta):
...
    @abstractmethod
    def __init__(self, n_components=2, scale=True, deflation_mode="regression",
                 mode="A", algorithm="nipals", norm_y_weights=False,
                 max_iter=500, tol=1e-06, copy=True):
...
    def fit(self, X, Y):
...
    def transform(self, X, Y=None, copy=True):
...
    def predict(self, X, copy=True):
...
    def fit_transform(self, X, y=None):
...
    def _more_tags(self):
        return {'poor_score': True}

D'autres classes héritent de cette classe _PLS, mais ABCMeta ne sort que pour le moment. La classe _PLS elle-même n'hérite que de Mixin et, du premier exemple, elle n'a pas d'héritage de la classe ABCMeta.

Ainsi, ʻabc.ABCMeta` est utilisé à nouveau, mais ** s'il y a une méthode qui doit être implémentée dans plusieurs classes, elle sera héritée dans la classe abstraite **.

(C'est un mystère de redéfinir fit_transform dans _PLS même s'il hérite de TransformerMixin.)

Conclusion

Dans cet article, à partir de l'exemple d'implémentation de TransformerMixin de scikit-learn, nous avons brièvement résumé comment créer une classe pour organiser les parties communes. C'est une pratique courante d'hériter de la classe ʻabc.ABCMeta pour en faire une classe abstraite, mais si vous voulez juste avoir une ou deux méthodes en commun pour plusieurs classes, utilisez ʻabc.ABCMeta. J'ai confirmé que cela semble peu probable. Il est ridicule de répéter la même implémentation encore et encore, alors faites bon usage de l'héritage de classe.

Les références

Comment utiliser ʻabc.ABCMeta` est présenté dans l'article suivant.

Recommended Posts

Pratique de l'héritage de classe en python comme vu dans sklearn
classe de cas en python
[Python] Héritage de classe, remplacement
Notation de classe en Python
Présentation de Python en pratique (PiP)
[Hikari-Python] Chapitre 09-03 Classe (Héritage)
Utilisez le tissu tel quel en python (fabric3)
Les mines terrestres cachées dans les variables de classe Python
Lire des morceaux PNG en Python (édition de classe)
Examiner la classe d'un objet avec python
Algorithme (arborescence de segments) en Python (s'entraîner)
Générer une collection de première classe en Python
Implémenter __eq__ etc. de manière générique dans la classe Python
Pratique d'utilisation de ceci en Python (mauvais)
Python: [Héritage] Réutilisation des constructeurs de superclasse dans les sous-classes
Classe Trump en Python (avec comparaison)
Comment utiliser __slots__ dans la classe Python
Générer une classe à partir d'une chaîne en Python
Python #inheritance (héritage)
Utilisez Python pour une sortie formatée telle que C / C ++ printf
Essayez de résoudre le problème de l'héritage de classe Python
[python] Différence entre variable et self. Variable dans la classe
J'ai écrit une classe en Python3 et Java
Trouvez des nombres premiers avec un code aussi court que possible en Python
Tutoriel Boost.NumPy pour l'extension de Python en C ++ (pratique)
Problème avec les variables pseudo-privées Python et l'héritage de classe
Comment générer "Ketsumaimo" en standard en Python
Utiliser python dans le conteneur Docker comme interpréteur Pycharm
Histoire de base de l'héritage en Python (pour les débutants)
Quadtree en Python --2
Python en optimisation
CURL en Python
Métaprogrammation avec Python
Python 3.3 avec Anaconda
[Python] classe, instance
Géocodage en python
SendKeys en Python
"Kanrika" la classe python
Méta-analyse en Python
Unittest en Python
À propos de python, classe
Époque en Python
Discord en Python
Allemand en Python
DCI en Python
tri rapide en python
nCr en python
À propos de l'héritage Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
Mon sklearn (Python)
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python