面向對象之繼承
什么是面向對象的繼承?
繼承(英語:inheritance)是面向對象軟件技術當中的一個概念。如果一個類別A“繼承自”另一個類別B,就把這個A稱
為“B的子類別”,而把B稱為“A的父類別”也可以稱“B是A的超類”。繼承可以使得子類別具有父類別的各種屬性和方法,而
不需要再次編寫相同的代碼。在令子類別繼承父類別的同時,可以重新定義某些屬性,并重寫某些方法,即覆蓋父類別的
原有屬性和方法,使其獲得與父類別不同的功能。另外,為子類別追加新的屬性和方法也是常見的做法。 一般靜態的面向
對象編程語言,繼承屬于靜態的,意即在子類別的行為在編譯期就已經決定,無法在執行期擴充。
class Person:def __init__(self,name,sex,age):self.name =nameself.age = ageself.sex = sex
class Cat:def __init__(self,name,sex,age):self.name = nameself.sex =sexself.age =age
class Dog:def __init__(self,name,age,sex):self.name =nameself.sex =sexself.age = age
# 定義三個不同的類class Animal(object):def __init__(self,name,sex,age):self.name = nameself.sex = sexself.age = age
# 定義一個Animal父類
class Person(Animal):pass
class Dog(Animal):pass
class Person(Animal):pass
# 派生三個子類
繼承的優點:
- 增加了類的耦合性(耦合性不宜多,宜精)。
- 減少了重復代碼。
- 使得代碼更加規范化,合理化。
繼承的分類
父類,又叫基類,超類,上面例子中的Animal就是一個父類。
子類,派生類,由父類派生而成的類,可以調用父類的靜態屬性和動態方法。
繼承:可以分單繼承,多繼承。
經典類和新式類:
在python2.2版本之前均為經典類,python2.2之后新式類和經典類并存,python3之后取消了經典類的概念、
簡單來說,在python2x基類的根如果什么也不寫就是經典類,如果python的根為object就為新式類
python3x版本中只有一種類:
python3中使?的都是新式類. 如果基類誰都不繼承. 那這個類會默認繼承 object
單繼承
類名,對象執行父類方法
class Aniaml(object):type_name = '動物類'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sexdef eat(self):print(self)print('吃東西')class Person(Aniaml):passclass Cat(Aniaml):passclass Dog(Aniaml):pass# 類名:
print(Person.type_name) # 可以調用父類的屬性,方法。
Person.eat(111)
print(Person.type_name)
執行順序
class Animal(object): # 1type_name = "動物類" # 6def __init__(self,name,sex,age): # 7self.name = name # 8self.sex = sex # 9self.age = age # 10def eat(self):print(self)print("吃東西")
class Person(Animal): # 2def eat(self): # 11print("%s 吃飯"%self.name) # 13
class Cat(Animal): # 3pass
class Dog(Animal): # 4pass
p1 = Person("alex","laygirl",34) # 5
p1.eat() # 12
# 結果:
alex 吃飯
# 實例化對象時必須執行__init__方法,類中沒有,從父類找,父類沒有,從object類中找。
# 先要執行自己類中的eat方法,自己類沒有才能執行父類中的方法。
同時執行類以及父類中的方法
1.方法一:
如果想執行父類的func方法,這個方法并且子類中也用,那么就在子類的方法中寫上:
父類.func(對象,其他參數)
class Aniaml(object):type_name = '動物類'def __init__(self,name,sex,age):self.name = nameself.age = ageself.sex = sex # 繼承父類中的三個靜態屬性def eat(self):print('吃東西')class Person(Aniaml):def __init__(self,name,sex,age,mind):Aniaml.__init__(self,name,sex,age) # 方法一self.mind = mind # 封裝mind屬性def eat(self):super().eat()print('%s 吃飯'%self.name)
class Cat(Aniaml):passclass Dog(Aniaml):pass
p1 = Person('春哥','laddboy',18,'有思想')
print(p1.__dict__)
2.利用super,super().func(參數)(父類的重構)
class Animal:def __init__(self,name,sex,age):self.name = nameself.sex = sexself.age = agedef eat(self):print("動物都需要吃飯")
class Human(Animal):def __init__(self,name,sex,age,hobby):super(Human,self).__init__(name,sex,age) # 繼承父類中的三個靜態屬性self.hobby = hobbydef eat(self):super().eat() # 執行父類中的eat方法print(f"{self.name}都需要吃飯")
class Dog(Animal):pass
class Cat(Animal):pass
H1 = Human("小紅","女",18,"看書")
H1.eat()
# 結果:
"動物都需要吃飯"
"小紅都需要吃飯"
單繼承經典練習題:
# 1
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)class Foo(Base):pass
obj = Foo(123)
obj.func1() # 123 運?的是Base中的func1 # 2
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)
class Foo(Base):def func1(self):print("Foo. func1", self.num)
obj = Foo(123)
obj.func1() # Foo. func1 123 運?的是Foo中的func1 # 3
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)
class Foo(Base):def func1(self):print("Foo. func1", self.num)
obj = Foo(123)
obj.func1() # Foo. func1 123 運?的是Foo中的func1
# 4
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print("Base.func2")
class Foo(Base):def func2(self):print("Foo.func2")
obj = Foo(123)
obj.func1() # 123 Foo.func2 func1是Base中的 func2是?類中的
# 再來
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print(111, self.num)
class Foo(Base):def func2(self):print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:obj.func2() # 111 1 | 111 2 | 222 3# 再來
class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print(111, self.num)
class Foo(Base):def func2(self):print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:obj.func1() # 那筆來吧. 好好算
多繼承
class A:def __init__(self,name):self.name = namedef show_name(self):print(f"A的名字為{self.name}")
class B:def __init__(self,name):self.name = namedef show_name(self):print(f"B的名字為{self.name}")
class C(A,B): # C同時繼承A,B類pass
c = C("A")
print(c.name)
c.show_name()
在python這種,經典類和新式類繼承父類所使用的算法是完全不同的
經典類的多繼承
經典類的多繼承采用深度優先算法
class A:pass
class B(A):pass
class C(A):pass
class D(B, C):pass
class E:pass
class F(D, E):pass
class G(F, D):pass
class H:pass
class Foo(H, G):pass
類的: Foo-> H -> G -> F -> E -> D -> B -> A -> C.
新式類的多繼承
mro序列
MRO是一個有序列表L,在類被創建時就計算出來
通用計算公式為:
mro(Chird(Base1,Base2)) = [child] + merge(mro(Base1),mro(Base2),[Base1,Base2])
# 其中child繼承自Base1,Base2
如果繼承一個基類:class B(A)
這時候B的mro序列為
mro(B) = mro(B(A))
= [B] + merge(mro(A) + [A])
= [B] + merge([A] + [A])
= [B,A]
如果繼承至多個基類:class B(A1,A2,A3)
mro(B) = mro( B(A1, A2, A3 …) )
= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
= ...
計算結果為列表,列表中至少有一個元素即類自己,如上述示例[A1,A2,A3],merge操作是C3算法的核心
表頭和表尾
表頭:
列表的第一個元素
表尾:
列表中表頭以外的元素集合(可以為空)
示例
列表:[A, B, C]
表頭是A,表尾是B和C
列表之間的+操作
+操作:
[A] + [B] = [A, B]
(以下的計算中默認省略)
如計算merge( [E,O], [C,E,F,O], [C] )
有三個列表 : ① ② ③
merge不為空,取出第一個列表列表①的表頭E,進行判斷 各個列表的表尾分別是[O], [E,F,O],E在這些表尾的集合中,因而跳過當前當前列表
取出列表②的表頭C,進行判斷C不在各個列表的集合中,因而將C拿出到merge外,并從所有表頭刪除merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
進行下一次新的merge操作 ......
---------------------
計算mro(A)方式:
mro(A) = mro( A(B,C) )原式= [A] + merge( mro(B),mro(C),[B,C] )mro(B) = mro( B(D,E) )= [B] + merge( mro(D), mro(E), [D,E] ) # 多繼承= [B] + merge( [D,O] , [E,O] , [D,E] ) # 單繼承mro(D(O))=[D,O]= [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并刪除D= [B,D,E] + merge([O] , [O])= [B,D,E,O]mro(C) = mro( C(E,F) )= [C] + merge( mro(E), mro(F), [E,F] )= [C] + merge( [E,O] , [F,O] , [E,F] )= [C,E] + merge( [O] , [F,O] , [F] ) # 跳過O,拿出并刪除= [C,E,F] + merge([O] , [O])= [C,E,F,O]原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])= [A,B] + merge( [D,E,O], [C,E,F,O], [C])= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳過E= [A,B,D,C] + merge([E,O], [E,F,O])= [A,B,D,C,E] + merge([O], [F,O]) # 跳過O= [A,B,D,C,E,F] + merge([O], [O])= [A,B,D,C,E,F,O]
---------------------