オリジナルのポストアドレスします。https://www.cnblogs.com/lx3822/p/8808845.html
継承
1:継承されている何
継承はPythonで、新しいクラスはPythonで息子の多重継承の父をサポートする1つまたは複数の親クラスを継承することができ、新しいクラスを作成する方法です。
新しいクラスまたはサブクラスは、派生クラスになるために。
親と基底クラスやスーパークラスになることができます。
親クラスの遺伝的性質をサブクラス。
2:なぜ利用の継承
(、繰り返し書き込みコードです)、コードの冗長性を削減します。
3:どのように継承:
我々は2つのクラスを定義し、
クラスparenclass1:
パス
クラスparenclass2: パス
二つのクラスの定義では:
クラスsubclass1:パスクラスsubclass2:パス私がしたい:クラスparenclass1:クラスsubclass1として:親を。パスがパス
:この使用すべきクラスsubclass1(parenclass1):サブクラスであるsubclass1この手段は、parenclassはsubclass1親パスは、
どのように言葉の2つの親クラスの表現?次のように:クラスsubclass2は(parenclass1、parenclass2):パスこの手段subclass2親ですparenclass1、parenclass2両方
__bases__で次のように親クラスのサブクラスがそれを見るべきか見てみたいです。
クラスParentClass1:
パス
クラスParentClass2: パス
クラスSubclass1(ParentClass1):パス・クラスSubclass2(ParentClass1、ParentClass2):パス印刷(Subclass1 .__ bases__)#打印结果:(< クラス' __main __ ParentClass1。'> 、)プリント(Subclass2 .__ bases__)#打印结果:(< クラス' __main __。ParentClass1 '> 、< クラス' __main __。ParentClass2 '>)
クラシックと新しいスタイルのクラス
1 、唯一Caifen、のpython3は新しいカテゴリに統一されている中で、古典的なpython2で新しいクラスとクラス
2 クラスオブジェクトクラスの継承を示していないが、このクラスがで古典python2内のクラスのサブクラスである 3 python2で、 、継承されたオブジェクトクラスの表示だけでなく、このクラスのサブクラスで新しいクラス宣言4 オブジェクト継承するか否か、であるオブジェクト、継承デフォルトでは、すべてのクラスは、新しいクラスとクラシックの新しいクラスについてのpython3ある、のpython3では、違いについては後述します。ヒント:あなたは、基本クラスを指定しない場合は、Pythonのクラスは、デフォルトのオブジェクトクラスを継承する、オブジェクトクラスは、すべてのPythonの基本クラスです。
第二に、継承と抽象
継承は子と親クラスとの間の関係は、それをどうするかである説明しますか?見つけるには、この関係は、連続して抽象的でなければなりません。
抽象即ち、抽出又は類似の部分には、より似ています。
要約は、次の2つのレベルに分かれています。
1.オバママッセイ、多分より多くの部分を抽出カテゴリーへのオブジェクト等。
より多くの親クラスへの抽出物の一部のような2人、豚、犬三つのクラス。
抽象最も重要な役割は、(あなたは、懸念を分離する複雑さを軽減することができます)のカテゴリに分かれて
継承:言語をプログラミングすることによって、それを達成するために、抽象的な結果に基づいており、それは継承の仕方によって抽象的構造を表現するために、抽象化のプロセスを経るために、確かに資格があります。
ただ、抽象プロセスの分析と設計、動きやスキルは、あなたが抽象クラスを介して取得することができます
例えば:私たちは、相続に関連していない場合は、次に我々が正常に書き込まれ、クラスの古い男の子の教師と生徒が書きました
クラスOldboyTeacher:
学校= ' oldboy ' デフ__init __(自己、名前、年齢、性別):self.name = 名前self.age = 年齢self.sex = change_scoreデフセックス(自己):プリント(' 教師%sがスコア変化している%の' 自己を.nameの)クラスOldboystudent:
学校= 'oldboy'
デフ__init __(自己、名前、年齢、性別):
self.name = 名前
self.age = 年齢
self.sex = セックス
デフ(自己)を選択します。 印刷(' 学生の%sのコース選択は' %self.name)tea1 = OldboyTeacher(' エゴン'、18、' 男性' )#OldboyTeacher .__のinit __(...)STU1 = Oldboystudent(' アレックス'、73、' 女性' )プリント(tea1.name、tea1.age、tea1.sex)#エゴン18雄
プリント(stu1.name)#alex
しかし、分析の後、我々は、我々が書き込みに継承されたクラスを使用することができ、重複したコードがたくさんあることがわかりました。次のとおりです。
クラスOldboyPeople:
学校= ' oldboy ' デフ__init __(自己、名前、年齢、性別):self.name = 名前self.age = 年齢self.sex = セックスクラスOldboyteacher(OldboyPeople):デフchange_score(自己):プリント(「教師%sのスコア変化している'%のself.nameを)
クラスOldboystudent(OldboyPeople):デフ(自己)を選択します:印刷(' sのコース選択学生%が'%のself.name)tea1 = Oldboyteacher(' エゴン」、18、' 男性' )STU1 = Oldboystudent(' アレックス'、73 ' 女性' )
プリント(tea1.name、tea1.age、tea1.sex)#egon 18 雄プリント(stu1.name)#alex
第三に、継承されたプロパティのルックアップウォッチングに基づきます
私たちは、列子を見て
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
Foo:
def f1(self):
print(
'Foo.f1'
)
def f2(self): #self=obj
print(
'Foo.f2'
) #在父类中找到发 f2属性,第3步打印这一行
self.f1() #obj.f1() 第4步再去掉用self的f1属性
class
Bar(Foo):
def f1(self):#第五步, 在回到
object
自身的名称空间找f1属性,找到后调用
print(
'Bar.f1'
) #第6步 执行
obj=Bar() #第一步 :类的实例化, 先得到一个空对象,
obj.f2() #第2步:空对象调用f2属性 在自身寻找f2属性, 没有找到就去父类中寻找<br><br>#结果
|
Foo.f2
Bar.f1
注サブクラス属性検索、優先順位は、それ自体では親クラスで検索する独自のサブクラス独自の属性や特性を見つけなければならないケースではありません。
obj.f2実行するときにこれは非常に興味深いです、彼は確かに非常に安いあなたは、f2のプロパティを見つけるself.f1を実行するときに、親クラスの属性を見つけるために、その属性でなく、自分の財産を見つけるself.f1優先順位を取り、しませんでした。
自分自身に最初に行く性質が自己であるに自己の重要な、自己。
第四に、派生
派生:独自の主題のサブクラス、親クラスと同じ名前場合は、新しいプロパティの独自のサブクラスを定義します。
クラスOldboyPeople:
school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def f1(self): print('爹的f1') class OldboyTeacher(OldboyPeople): def change_score(self): print('teacher %s is changing score' %self.name) def f1(self): print('儿子的f1') tea1 = OldboyTeacher('egon', 18, 'male') tea1.f1()
#调用显示:儿子的f1
# 父类和子类中都有f1, 优先调用自己的属性,所以结果调用的是儿子的f1
五、在子类中派生出的新方法重用父类的功能
拿上一案例来举例 在oldboyteacher 这个类中要添加薪水与级别。 然后调用。 有两种方式。
方式一:指名道姓的调用(与继承没有什么关系)
class OldboyPeople:
school ='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): print( ''' ====个人信息==== 姓名:%s 年龄:%s 性别:%s '''%(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): OldboyPeople.__init__(self,name,age,sex) #在这里指明道姓来调用这一个函数里的属性 self.level =level self.salary=salary def tell_info(self): OldboyPeople.tell_info(self) #指名道姓的来调用这个函数里的属性 print(""" 等级:%s 薪资:%s """ %(self.level,self.salary)) tea1 = OldboyTeacher('egon', 18, 'male', 9, 3.1) print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary) tea1.tell_info() #打印结果: egon 18 male 9 3.1 ====个人信息==== 姓名:egon 年龄:18 性别:male 等级:9 薪资:3.1
方法二、
用super()调用(严格依赖于继承)
super() 的返回值是一个特殊的对象,该对象专门用来调用父类中的属性, 一般在python2中,需要super(自己的类名,self), 而python3中,括号里面一般不填类名
class OldboyPeople:
school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def tell_info(self): print(""" ===========个人信息========== 姓名:%s 年龄:%s 性别:%s """ %(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level, salary): super().__init__(name,age,sex) self.level = level self.salary = salary def tell_info(self): super().tell_info() print(""" 等级:%s 薪资:%s """ %(self.level,self.salary)) tea1 = OldboyTeacher('egon', 18, 'male', 9, 3.1) print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary) tea1.tell_info() #调用结果: egon 18 male 9 3.1 ===========个人信息========== 姓名:egon 年龄:18 性别:male 等级:9 薪资:3.1
六:经典类 与新式类
1新式类:
继承object的类,以及该类的子类,都是新式类
在python3中,如果一个类没有指定继承的父类,默认就继承object
所以说在python3中所有的类都是新式类
2经典类:(只有在python2才区分经典类和新式类):
没有继承object的类,以及该类的子类 都是经典类
1 经典类:深度优先
2 新式类:广度优先
如果继承关系为非菱形结果吗则会按照先找B 这一条分支,然后在找c这一条分支,最后找D这一条分支的顺序,直到找到我们想要的属性
当继承关系为菱形结构时
经典类查找顺序:
若是在A 类里自己没找到, 则会先去B类里去找, B类里没找到,就会在E类里找, 然后在G类里找,
G类里没找到 会去C 类里找, 然后去F 类里找,最后去D 类里找。
新式类查找顺序:
按照图中1 ,2 , 3, 4,5,6的顺序查找, 这个为广度优先的查找方式
这个图 蛮好的,缺少了两个线,应该E(G)与F(G)也指向G(object),其实对于新式类的继承,基于广度与深度,我自己根本无法定论。
C3算法我没去仔细研究,但根据我自己的经验来看,会根据继承的类的顺序与深度相关。
下面上我自己写的测试代码:
class A(object): def ping(self): print('ping', self) class B(A): def pong(self): print('pong', self) class E(B): ... class F(object): ... class H(F): ... class C(H): def pong(self): print('PONG', self) class D(C, E): def ping(self): super(D, self).ping() print('post-ping', self) if __name__ == '__main__': print(D.__mro__)
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第十二章/diamond.py (<class '__main__.D'>, <class '__main__.C'>, <class '__main__.H'>, <class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) Process finished with exit code 0
从运行结果来看,C线继承到object之前,一致沿着C走,后面再沿着E走。
object是两个父类的相交的基类结合点。
class A(object): def ping(self): print('ping', self) class B(A): def pong(self): print('pong', self) class E(B): ... class F(object): ... class H(A): ... class C(H): def pong(self): print('PONG', self) class D(C, E): def ping(self): super(D, self).ping() print('post-ping', self) if __name__ == '__main__': print(D.__mro__)
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第十二章/diamond.py (<class '__main__.D'>, <class '__main__.C'>, <class '__main__.H'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) Process finished with exit code 0
I継承Hに符号A上記の二つの基本クラスの親クラスDそのような交点A、との観点から継承、Aの前にクラスCを見つけるための最初の行と最後のオブジェクトEを見つけます。
7:スーパー()の継承に依存しています
スーパー()を見つけるために、現在の位置からリストを表示して下さいMROに厳密に従って将来的に継続されます
クラスA:
デフテスト(自己):
(印刷「A.test 」)#2をこのステップでは、()スーパーを印刷している。F1#を。3 その後、F1の親クラスを呼び出し、将来的にC.mro A検索順序に従って実行さBを見つけるために行くことを続けますクラスB:DEF F1(自己):#4(印刷実行し、F1を発見' Bからの' #印刷)5。クラスC(A、B):合格C = C()印刷(C.mro())呼属性#オーダー[<クラス'に__main __ C '>、<クラス'に__main __ A'>、< '__main __ Bで'クラス>、<クラスのオブジェクト'>] c.test()#1:C全くGoは存在しませんでコール
#は結果を印刷
A.test
Bから