継承
Pythonのすべてのクラスはオブジェクトクラスのサブクラスであり、オブジェクトはタイプから継承します
継承は、インターフェイスの継承と実装の継承に分けられます
インターフェイスの継承:親クラスのインターフェイス名を使用すると、サブクラスがこのメソッドをオーバーライドします。可能な限りインターフェイスクラスを継承し、サブクラスにメソッドを実装し、インターフェイスクラスの複数の継承を促進します。これは、インターフェイスの分離の原則に従い、正規化された設計に役立ちます。抽象クラスの複数の継承はお勧めしません。
実装の継承:サブクラスは何も実装する必要はありません。親クラスのインターフェイスと実装を直接使用すると、コードの結合が強化されるため、お勧めしません。
詳細
クラスの継承は最終的にインスタンス化され、ほとんどの場合、クラスの代わりにオブジェクトを使用します。それでは見てみましょう〜
継承プロセス
継承はコードの再利用の手段にすぎず、すべてのコードがサブクラスのスペースにロードされ、メソッドが引き続き親クラスに属しているとは限りません。以下の例でわかるように、Cat.funcはまだAnimalです。より詳しく理解すると、funcもfuncであることがわかります。これは、Animalクラスにのみバインドされています。このクラスは、この関数を見つけるのに役立ちます。サブクラスは親クラスがこの関数を見つけて終了しました〜。
classAnimal(object):
def func(self):print("Animal.func")classDog(Animal):
def func(self):print('Dog.func')classCat(Animal):""" No func~ """print(Animal.func) # <function Animal.func at 0x103f79620print(Cat.func) # <function Animal.func at 0x103f79620print(Dog.func) # <function Dog.func at 0x104073510
インスタンス化のプロセス
プロパティとメソッドは、インスタンス化プロセス中にインスタンススペースに表示されません。それらはまだクラス自体に属しており、オブジェクトはそれらを見つけて呼び出すことしかできません。ただし、オブジェクトのプロパティを変更すると、同じ名前の属性がオブジェクトのスペースに作成されます。これはオブジェクトの属性です。複雑な継承の本質は同じです。
classAnimal(object):
def tell(self):print('self.name:%s Animal.name %s '%(id(self.name),id(Animal.name)))
name ='Animal'classCat(Animal):""" No func~ """
def tell(self):super().tell()print('self.name %s Cat.name %s '%(id(self.name),id(Cat.name)))
cat =Cat()
cat.tell()
cat.name ='django'
cat.tell()
# self.name:4473398472 Animal.name 4473398472
# self.name 4473398472 Cat.name 4473398472
# self.name:4474859736 Animal.name 4473398472
# self.name 4474859736 Cat.name 4473398472
単一の継承
このクラスに近いメソッドは、祖先のメソッドをオーバーライドします。これは、メソッドカバレッジまたはリライトと呼ばれます。原則として、Pythonの属性取得メカニズムは内部ネームスペースからクエリを実行します。
classMyClass(object):"""
A simple example class"""
MyClassName ='MyClass'
name ='MyClass'
def func(self):print("This is {}".format(self.__class__.name))
def get_name(self):print(self.name)classMySonClass(MyClass):
MySonClass ='MySonClass'
name ='MySonClass' #属性の書き換え
def get_name(self):super().get_name()print('親クラスのgetを書き直します_上記のnameメソッドは親クラスのメソッドです。私はサブクラスから来ています!')
person1 =MyClass()
person2 =MySonClass()
person1.func()
person2.func() #メソッドの実装はそれ自体を継承し、親クラスのメソッドを直接呼び出します。ただし、使用される属性は依然として独自のものです。
print('*'*40)
person1.get_name()
person2.get_name() #メソッドのインターフェースは継承され、このメソッドはサブクラスでオーバーライドされます。
# 結果
#------------------------------
# This is MyClass
# This is MySonClass
# ****************************************
# MyClass
# MySonClass
# 親クラスのgetを書き直します_上記のnameメソッドは親クラスのメソッドです。私はサブクラスから来ています!
複数の継承
形態的には、クラスの継承リストは1つでも複数でもかまいません。継承リストにクラスが1つしかない場合、つまり親クラスが1つしかない場合は、単一継承と呼ばれ、複数のクラスは複数継承と呼ばれます。
現代のクラスの継承方法は幅優先の継承であり、古典的なクラスの継承方法は深さ優先の継承です。
クラス継承の順序は、クラスの__mro__メソッドを使用して確認できます。
ダイヤモンドの継承
classA(object):
m ='a'classB(A):
m ='b'classC(A):
m ='c'classD(B,C):
# m ='d'
pass
x =D()print(x.m)
# Dのインスタンス化されたオブジェクトがm属性を取得すると、最初にそれ自体の名前名が検索され、検索順序はDになります。- B - C - A
super()メソッド
構文super(クラス、インスタンス化されたオブジェクト)。親クラスのメソッド
クラス内でsuper()メソッドを使用する場合、パラメーターも必要ありません。
super()メソッドが複数の継承で使用される場合、実行は親クラスのメソッドではなく、mroの上位レベルのメソッドになります。
複数継承の問題を解決するために、初期化メソッドが繰り返し呼び出されます。 (クラス名使用時。メソッド名)
super()メソッドを使用して「親クラス」(__mro__メソッドの前のクラス)のメソッドを実行する場合
# ダイヤモンドの継承における繰り返しの呼び出し
# 継承の検索順序に注意してください〜スーパーを使用してください()mro順に実行されます
classGrand(object):
def __init__(self, name):
self.name = name
print("class Grand ")classSonLeft(Grand):
def __init__(self, age, name):
self.age = age
Grand.__init__(self, name) #注:調整して実行し、確認してください
# super().__init__(age, name)print("class SonLeft")classSonRight(Grand):
def __init__(self, gender, name):
self.gender = gender
Grand.__init__(self, name) #注:調整して実行し、確認してください
# super().__init__(name)print("class SonRight")classGrandSon(SonLeft, SonRight):
def __init__(self, name, age, gender):
# super().__init__(age, name)
SonLeft.__init__(self, age, name) #注:調整して実行し、確認してください
SonRight.__init__(self, gender, name) #注:調整して実行し、確認してください
self.gender = gender
grand_son =GrandSon("Monkey",18,"男性")
上記はPythonでの継承の詳細な内容です。Python継承の詳細については、ZaLou.Cnの他の関連記事に注意してください。
Recommended Posts