Wie schreibe ich Klassenvererbung in Python? Ich werde eine praktische Ausgabe darüber schreiben. Es gibt keine Basisausgabe.
Dies scheint beim Erstellen von Software und umfangreichen Bibliotheken hilfreich zu sein. Wenn Sie eine Methode schreiben, die in mehreren Klassen in der abstrakten Klasse oder in der übergeordneten Klasse, die als Vorlage dient, auf dieselbe Weise definiert ist, müssen Sie sie nicht in der untergeordneten Klasse definieren.
Nehmen wir dieses Mal das "TransformerMixin" von scikit-learn, das jeder liebt, als Beispiel. TransformerMixin
ist eine Klasse, die überall beim Scikit-Lernen verwendet wird. In scikit-learn werden "fit" und "transform" häufig für die Vorverarbeitung usw. verwendet, und "fit_transform", das sie zusammen ausführt, wird in "Transformer Mixin" implementiert.
Dieser Mechanismus ist ein sehr einfaches Beispiel dafür, dass "fit_transform" nur durch Erben verwendet werden kann.
Als Referenz implementiert Python normalerweise eine abstrakte Klasse, die abc.ABCMeta
erbt. Es gibt ein Paket namens abc, das in Python immer verfügbar ist und zum Definieren abstrakter Klassen verwendet wird. Siehe auch die Referenzen am Ende dieses Artikels.
Ich habe die folgenden zwei Punkte ausprobiert. Ich werde schreiben.
Lesen wir zuerst den folgenden Code. Es stammt aus der Github-Seite von 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)
...
Beim Definieren einer abstrakten Klasse in Python wird häufig eine Klasse namens "abc.ABCMeta" verwendet. Im obigen Beispiel wird jedoch nur die Methode ohne Verwendung von "abc.ABCMeta" definiert.
In der abstrakten Klasse mit abc.ABCMeta
und @ abc.abstractmethod
können Sie eine Klasse erstellen, die die Implementierung am geerbten Ziel erzwingt.
Auf der anderen Seite möchten wir mit TransformerMixin oben allen Vererbungszielen nur gemeinsame Methoden zur Verfügung stellen. In diesem Fall müssen Sie nicht "abc" verwenden.
Ich werde versuchen zu schreiben. Wenn Sie eine abstrakte Klasse verwenden, die "abc" verwendet, funktioniert dies wie folgt. Darüber hinaus machen Sie sich bitte keine Sorgen, da der Funktionsname usw. Abekobe ist ...
$ 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
Es gibt eine Methode "score" mit einem "@ abstractmethod" -Dekorator im "DensityMixin" der abstrakten Klasse, die jedoch nicht im geerbten "OneClassSvm" ** Keshikaran implementiert ist! Die Fehlermeldung lautet **.
Wenn Sie die Score-Funktion von OneClassSvm auskommentieren, funktioniert sie wie folgt.
$ python sampleAbsclass.py
echo echo hello hello
100 10
Eine weitere Einschränkung, die auftritt, wenn Sie "abc.ABCMeta" stark nutzen, besteht darin, dass Klasse A mehrere abstrakte Klassen erbt. "Wenn auch nur eine Klasse A eine abstrakte Klasse hat, die" abc.ABCMeta "erbt, müssen die anderen geerbten Klassen auch" abc.ABCMeta "erben." Es gibt einen Punkt. Wenn Sie dies unterbrechen, wird die folgende Fehlermeldung angezeigt.
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Dies geschieht auch in anderen Sprachen, daher halte ich es für zweckmäßig, dies zu tun. Sie sollten die Theorie der Programmiersprache richtig lernen ...
Es gibt eine Implementierung von scikit-learn, die abc.ABCMeta
verwendet. Schauen wir uns also auch dort um. Das Folgende wird aus _PLS --scikit-learn zitiert. Sie können sehen, dass "@ abstractmethod" nur zur "__init __" -Methode hinzugefügt wird.
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}
Andere Klassen erben diese _PLS-Klasse, ABCMeta wird jedoch erst zu diesem Zeitpunkt veröffentlicht. Die _PLS-Klasse selbst erbt nur Mixin und hat ab dem ersten Beispiel keine Vererbung der ABCMeta-Klasse.
Was also die Verwendung von abc.ABCMeta
betrifft, ** wird eine Methode, die in mehreren Klassen implementiert werden muss, in die abstrakte Klasse geerbt **.
(Es ist ein Rätsel, fit_transform
in _PLS
neu zu definieren, obwohl es TransformerMixin
erbt.)
In diesem Artikel haben wir ausgehend vom Implementierungsbeispiel von TransformerMixin
von scikit-learn kurz zusammengefasst, wie eine Klasse zum Organisieren gemeinsamer Teile erstellt wird.
Es ist üblich, die Klasse "abc.ABCMeta" zu erben, um sie zu einer abstrakten Klasse zu machen. Wenn Sie jedoch nur eine oder zwei Methoden haben möchten, die mehreren Klassen gemeinsam sind, verwenden Sie "abc.ABCMeta" Ich habe bestätigt, dass dies unwahrscheinlich erscheint.
Es ist albern, dieselbe Implementierung immer wieder zu wiederholen, also nutzen Sie die Klassenvererbung.
Die Verwendung von abc.ABCMeta
wird im folgenden Artikel vorgestellt.
Recommended Posts