Class inheritance practice in python as seen in sklearn

Introduction

How to write class inheritance in Python? I will write a practical edition about. There is no basic edition.

When is it important?

It seems to be useful when creating software and large-scale libraries. If you write a method that is defined in the same way in multiple classes in an abstract class or a parent class that serves as a template, you do not need to define it in a child class.

This time, let's take scikit-learn's TransformerMixin, which everyone loves, as an example. TransformerMixin is a class used everywhere in scikit-learn. In scikit-learn, fit and transform are often used for preprocessing etc., and fit_transform that performs them together is implemented in Transformer Mixin.

This mechanism makes fit_transform available just by inheriting, which is a very simple example.

For reference, python usually implements an abstract class that inherits from ʻabc.ABCMeta`. There is a package called abc that is always available in Python, and it is used to define abstract classes. See also the references at the end of this article.

abc — Abstract Base Classes

What I tried

I tried the following two points. I will write.

  1. Source code reading
  2. Moved the sample code

Source code reading

Let's read the code below first. Quoted from scikit-learn's github page. 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)
...

When defining an abstract class in Python, a class called ʻabc.ABCMeta is often used. However, in the above example, only the method is defined without using ʻabc.ABCMeta.

ʻAbstract classes that use abc.ABCMeta and @ abc.abstractmethod can be inherited to create classes that force implementation. On the other hand, with TransformerMixin above, we just want to make common methods available to all inheritance destinations. In this case, you don't have to use ʻabc.

Sample code moved

I will try writing. If you use an abstract class that uses ʻabc`, it works as follows. In addition, please do not worry because the function name etc. is 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

There is a method score with a @ abstractmethod decorator in the DensityMixin of the abstract class, but it is not implemented in the inherited ʻOneClassSvm` ** Keshikaran! The error message is **.

If you uncomment the score function of ʻOneClassSvm`, it works as below.

$ python sampleAbsclass.py
echo echo hello hello
100 10

Others: Precautions when using abc.ABCMeta

Another caveat that comes up when you make heavy use of ʻabc.ABCMeta is when class A inherits multiple abstract classes. "If even one class A has an abstract class that inherits ʻabc.ABCMeta, then the other inherited classes must also inherit ʻabc.ABCMeta`." There is a point. If you break this, you will get the following error message.

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

This is the same phenomenon in other languages, so I think it's convenient to do so. You should learn the theory of programming languages properly ...

Other 2 Example using abc.ABCMeta

There is an implementation of scikit-learn that uses ʻabc.ABCMeta, so let's take a look there as well. The following is quoted from [_PLS --scikit-learn](https://github.com/scikit-learn/scikit-learn/blob/1495f69242646d239d89a5713982946b8ffcf9d9/sklearn/cross_decomposition/pls_.py#L120). You can see that @abstractmethod is added only to the init` method.

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}

Other classes inherit this _PLS class, but ABCMeta comes out only at this time. The _PLS class itself inherits only Mixins, and from the first example, it does not have any inheritance from the ABCMeta class.

So, ʻabc.ABCMeta` will be used again ** if there is a method that must be implemented in multiple classes, it will be inherited in the abstract class **.

(It's a mystery to redefine fit_transform in _PLS even though it inherits TransformerMixin.)

Conclusion

In this article, starting from the implementation example of TransformerMixin of scikit-learn, I briefly summarized how to create a class to organize common parts. It is a common practice to inherit the ʻabc.ABCMeta class to make it an abstract class, but if you just want to have one or two methods in common for multiple classes, use ʻabc.ABCMeta. I confirmed that it seems unlikely. It's silly to repeat the same implementation over and over, so make good use of class inheritance.

References

How to use ʻabc.ABCMeta` is introduced in the following article.

-I tried various things with the abstract class of Python --Qiita -How to create an abstract class in Python !!

Recommended Posts

Class inheritance practice in python as seen in sklearn
case class in python
[Python] Class inheritance, override
Class notation in Python
Introducing Python in Practice (PiP)
[Python of Hikari-] Chapter 09-03 Class (inheritance)
Use fabric as is in python (fabric3)
Landmines hidden in Python class variables
Read PNG chunks in Python (class)
Examine the object's class in python
Algorithm (segment tree) in Python (practice)
Generate a first class collection in Python
Implement __eq__ etc. generically in Python class
(Bad) practice of using this in Python
Python: [Inheritance] Reuse superclass constructors in subclasses
Playing card class in Python (with comparison)
How to use __slots__ in Python class
Generate a class from a string in Python
Python #inheritance (inheritance)
Output formatted output in Python, such as C / C ++ printf.
Try to solve the Python class inheritance problem
[python] Difference between variables and self. Variables in class
I wrote a class in Python3 and Java
Find prime numbers in Python as short as possible
Boost.NumPy Tutorial for Extending Python in C ++ (Practice)
Practice applying functions and global variables in Python
Trouble with Python pseudo-private variables and class inheritance
How to output "Ketsumaimo" as standard output in Python
Use python in Docker container as Pycharm interpreter
Basic story of inheritance in Python (for beginners)
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
[Python] class, instance
Geocoding in python
SendKeys in Python
"Kanrika" python class
Meta-analysis in Python
Unittest in python
About python, class
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
About python inheritance
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
My sklearn (python)
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python