1.初期の継承
何継承されています
継承は、プログラムに、2つのオブジェクト間の関係を記述する、オブジェクト指向の概念であり、それは、クラス間の継承関係を説明しました
たとえば:Bの連続、bは.Aと呼ばれるサブクラスのプロパティとメソッドを使用することができ、Bは、親クラスと呼ばれ、基底クラスとも呼ばれています
なぜ使用の継承
すでに当事者であるものを使用することができる場所を継承するので、あなたは、コードの再利用性を向上させることができます
継承を使用する方法
継承のための基本的な構文
1 クラスA: 2つの #親クラスのメソッドおよびプロパティ 3。 A = 1。 4。 DEF A1(自己): 5 プリント(' A1 ' ) 6。 7つの。 クラスB(A): 8つの #サブクラスのメソッドとプロパティ 。9 パス 10 B = B() #のBサブクラスは、インスタンスBオブジェクト 。11 プリント(BA) #属性に親クラスAを使用して 12である b.a1() #の親クラスAの使用
2.抽象化と継承
すなわち、新たなクラスを形成し、同じ部分又はオブジェクトクラス番号を抽出抽象
抽象化の二つのレベル:
1.クラス抽出に同じ特性および挙動を有するオブジェクトの数
2クラスの数は、親クラスを抽出するために同一のプロパティとメソッドを有します
継承が抽象結果に基づいており、それは最初の抽象化のプロセスを経る、結果は、継承された抽象メソッドで表現することができ、プログラミング言語によって達成しました
継承の適切な使用:
1.最初に抽象して、継承
2.既存のクラスを継承し、元の機能を拡張または変更
検索順序の3. [プロパティ
オブジェクトまで----> ..... ---->クラス---->親クラス---->親クラスの親クラスオブジェクト:属性の順序を探します
1 位配列属性検索 2 クラス Aを: #親クラスAがXを定義 3 X = 1〜 4。 5。 クラス Bは、(A): #1 サブクラスBはまた、Xを定義する 。6 X = 2 。7 。8、B = B() 9 プリント(BX) #オブジェクトが中Bのサブクラスの定義を見つけることである前に検索 10 BX =を3つの #1 もX定義オブジェクト 。11 プリント(BX) #Xを定義した後に、そのオブジェクトのプロパティを見つけることです
見つけるために行くための親クラスを見つけることができない、探しに行くためにクラスを見つけることができない、見つけるために、オブジェクトに移動し、発見されたこれまでのオブジェクトは、エラーを見つけることができません
4.派生し、カバー
派生クラスとは何ですか
サブクラスは異なる内容で親クラスに表示されたら、このサブクラスは、それは、派生クラスと呼ばれている。通常の状況下で、私たちは親クラスを作成し、完全に同一サブクラス化することはできません、ので、サブクラスを失いますサブクラスは基本的にクラスを派生しているので意味は、我々は、いくつかのコードを追加します。
1 # 派生类 2 class Person: 3 def say_hi(self): # 父类中有一个方法 4 print('hi') 5 6 class Student(Person): 7 def say_hello(self): # 子类中也有一个新的方法 8 print('hello') # 此时这个子类就叫做派生类 9 10 s1 = Student() # 实例化一个类的对象 11 s1.say_hi() # 子类的对象可以调用父类的方法 12 s1.say_hello()
覆盖也称重写(overrides),当子类出现了和父类名称完全一致的属性或者方法时就叫做覆盖
1 # 覆盖 2 class Person: 3 x = 1 # 父类中有一个属性 4 def say_hi(self): # 父类中有一个方法 5 print('hi') 6 7 class Student(Person): 8 x = 2 # 子类中有一个同名的属性 9 def say_hi(self): # 子类中也有一个同名的方法 10 print('hello') 11 12 s1 = Student() 13 print(s1.x) # 打印的是子类中的属性 14 s1.say_hi() # 打印的是子类中的方法
5.子类访问父类的内容
访问的语法
语法: ```python 方式1: super(当前类名称,self).你要调的父类的属性或方法 方式2: super().你要调的父类的属性或方法 方式3: 类名称.你要调的父类的属性或方法(self) #方式3与继承无关 ```
子类访问父类的例子
1 # 子类访问父类的内容 2 class Person: 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 def eat(self): 8 print('%s会吃东西'%self.name) 9 10 class Student(Person): 11 def __init__(self,name,age,id): 12 # 第一种,父类名直接调用,这种方法什么地方都可以调用,与继承无关,并且需要写上对象本身 13 Person.__init__(self,name,age) 14 # 第二种,super(类名,对象本身),是python2内置的 15 super(Student,self).__init__(name,age) 16 # 第三种,python3做了优化可以内部不传参,推荐使用 17 super().__init__(name,age) 18 self.id = id 19 20 def eat(self): 21 super().eat() # 第三种方法在访问父类的方法 22 super(Student,self).eat() # 第二种方法在访问父类的方法 23 print('%s吃更好的东西'%self.name) 24 25 s1 = Student('sxc',18,188) 26 s1.eat()
初始化方法必须调用super
当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数
需求:person父类中有name,age两个属性,子类student中我需要增加一个id的属性
1 # 继承中初始化方法必须调用super 2 class Person: 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 class Student(Person): 8 def __init__(self,name,age,id): # 当子类需要增加属性时,需要再初始化一次,这时会覆盖父类的初始化方法 9 super().__init__(name,age) # 子类初始化方法必须加super,这样就能导入父类的初始化方法 10 self.id = id # 增加了id属性,原属性也能访问 11 12 def say(self): 13 print('%s说我真帅'%self.name) # 如果不初始化方法不调用super,self.name就找不到,会报错 14 15 s1 = Student('sxc',18,1414) 16 s1.say()
练习:实现一个可以限制元素类型的容器(字符串,元组,列表,字典,集合)
1 # 实现一个可以限制元素类型的容器 (字典,列表,元组,集合,字符串) 2 class Newlist(list): 3 def __init__(self,kind): 4 super().__init__() # 调用父类的初始化方法 5 self.kind = kind 6 7 def append(self,obj): 8 if type(obj) == self.kind: 9 super().append(obj) # 调用父类的append方法 10 print('加入成功') 11 else: 12 print('类型错误') 13 14 n = Newlist(int) # 定义数据类型为int 15 n.append(123543) 16 print(n)
6.组合
组合是一种关系,描述两个对象之间有什么关系.将一个对象作为另一个对象的属性
组合一般都是在初始化方法时定义另一个对象
组合的目的:为了重用现有代码,提高代码的重用性
组合的例子
1 # 组合:一个类作为另一个类的属性,两者没有关联 2 # 定义一个英雄类 3 class Hero: 4 def __init__(self,name,ad,hp,weapon): 5 self.name = name 6 self.ad = ad 7 self.hp = hp 8 self.weapon = weapon # 英雄类和武器类没有关联,想要英雄类使用武器类,必须在初始化时就增加一个武器的属性 9 # def attack(self,enemy): 10 # enemy.hp -= self.ad 11 # print('%s攻击了%s,掉了%s血,血量还剩%s'%(self.name,enemy.name,self.ad,enemy.hp)) 12 13 # 定义一个武器类 14 class Weapon: 15 def __init__(self,name,att): 16 self.name = name 17 self.att = att 18 19 def weapon(self,hero,enemy): 20 enemy.hp -= self.att 21 print('%s使用了%s攻击了%s,掉了%s血,血量还剩%s' % (hero.name,self.name,enemy.name, self.att, enemy.hp)) 22 23 w1 = Weapon('无尽之刃',100) # 定义一把武器 24 h1 = Hero('亚索',50,500,w1) # 定义一个攻击者 25 h2 = Hero('提莫',20,400,w1) # 定义一个敌人 26 27 h1.weapon.weapon(h1,h2) # 英雄用武器攻击了另一个英雄
什么时候使用继承:一个类是否包含了另一个类,即什么是什么的关系
什么时候使用组合:两个类的关联不大,即什么有什么的关系
7.多继承的问题:菱形继承(了解)
新式类和经典类
新式类:任何直接或者间接的继承于object的类就称之为新式类.(python3中的类的顶部都是object,所以python3中全是新式类)
经典类:不是object的子类,只有python2中有
新式类的继承顺序,先深度遍历,当遇到共同的父类时就广度遍历
新式类的继承顺序还可以通过调用mro方法来查看
1 # 定义类 2 class A: 3 pass 4 5 class B: 6 pass 7 8 class C(A): 9 pass 10 11 class D(A): 12 pass 13 14 class E(B): 15 pass 16 17 class F(C): 18 pass 19 20 class G(D): 21 pass 22 23 class H(E,F,G): 24 pass 25 26 print(H.mro())
新式类的继承顺序:H---->E---->B---->F---->C---->G---->D---->A
经典类的继承顺序,全部都是深度遍历
经典类的继承顺序:H---->E---->B---->F---->C---->A---->G---->D