2. 繼承
繼承的第一個作用
第一階段:繼承的作用
class Animal(object):
def run(self):
print("Animal is running")
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
cat = Cat()
dog.run()
cat.run()
Animal is running
Animal is running
上面Animal就是父類,子類就是Dog和Cat,因為Dog和Cat繼承了Animal,子類會擁有父類的所有方法。
總結:
1. 當子類繼承父類后,子類就會擁有父類的所有方法
繼承的第二個作用:子類重寫方法后,優先調用子類方法
第二階段:當子類繼承父類后,子類寫了一個run方法,父類也寫了一個run方法,子類調用run方法時,應該調用父類的run還是子類的?
# 子類繼承父類的方法
class Animal(object):
def run(self):
print("Animal is running")
class Dog(Animal):
def run(self):
print("Dog is running")
class Cat(Animal):
def run(self):
print("Cat is running")
dog = Dog()
cat = Cat()
# 調用方法
dog.run()
cat.run()
Dog is running
Cat is running
由此可以看出,優先調用子類的方法
總結:
1. 當子類擁有和父類相同的方法時,優先調用子類的方法。
繼承的第三個作用:類的派生
class person(object):
def __init__(self, weight):
self.weight = weight
def eat(self):
print("正在吃東西")
class Student(person):
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
a = Student('plf', 18, '男')
a.eat()
print(a.name, a.age, a.sex)
正在吃東西
plf 18 男
對於以上的代碼,提出一個疑問:既然Student類繼承了person類,那么Student初始化的對象就擁有了person類的方法,但是對應person的屬性weight,Student似乎沒有繼承到,那么我們如何在初始化Student對象時,擁有父類的weight屬性?同時擁有不同於父類的屬性?
class person(object):
def __init__(self,weight):
self.weight = weight
class Student(person):
def __init__(self,name,age,sex,weight):
self.name = name
self.age = age
self.sex = sex
super().__init__(weight) # 調用了父類的__init__方法,並將weight傳給了person
a = Student('plf',18,'男',140)
print(a.name,a.age,a.sex,a.weight)
因此想要得到父類的屬性,必須要在子類的初始化方法中(__init__函數)中調用父類的方法:super()._init_(args,*kwargs) 這樣就能拿到父類的屬性並賦值 最后變成自己的屬性,同時子類有不同於父類的屬性。子類繼承父類,子類有父類的屬性,且子類有不同於父類的屬性,那么這一過程我們成為類的派生
經典類和新式類
什么是經典類 什么事是新式類
'''
Python 2 當中類分為新式類和經典類
Python 3中全部叫新式類
python 2中如果有繼承父類是object 就是新式類,繼承其他類不算,但是如果繼承其他類,其他類有其他了object 那就是新式類
'''
# 經典類
class 類名:
pass
# 新式類
class 類名(object):
pass
經典類的繼承特點:深度優先
新式類的繼承特點:廣度優先
使用代碼證明
class G(object):
def test(self):
print('from G')
class E(G):
def test(self):
print('from E')
class F(G):
def test(self):
print('from F')
class B(E):
def test(self):
print('from B')
class C(F):
def test(self):
print('from C')
class D(G):
def test(self):
print('from D')
class A(B,C,D):
def test(self):
print('from A')
a=A()
a.test()
print(A.__mro__) #只有新式才有這個屬性可以查看線性列表,經典類沒有這個屬性
#新式類繼承順序:A->B->E->C->F->D->G
#經典類繼承順序:A->B->E->G->C->F->D
#python3中統一都是新式類
#pyhon2中才分新式類與經典類
from A
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>)
繼承原理(python如何實現的繼承)python2中沒有_mro_
python到底是如何實現繼承的,對於你定義的每一個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如
>>> A.mro() #等同於A.__mro__
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>)
為了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。
而這個MRO列表的構造是通過一個C3線性化算法來實現的。我們不去深究這個算法的數學原理,它實際上就是合並所有父類的MRO列表並遵循如下三條准則:
1.子類會先於父類被檢查
2.多個父類會根據它們在列表中的順序被檢查
3.如果對下一個類存在兩個合法的選擇,選擇第一個父類