甚麼是繼承?
class ParentClass1 : #定義父類 pass class ParentClass2 : #定義父類 pass class SubClass1(ParentClass1):
#單繼承,基類是ParentClass1,派生類是SubClass pass class SubClass2(ParentClass1,ParentClass2):
#python 支持多繼承,用逗號分隔開來多個繼承的類 pass
查看繼承
subclass1.__bases__#__base__只查看從左到右繼承的第一個字類,# __bases__ 則是查看所有繼承的父類(<class'__main__.ParentClass1'>,) subclass2. __bases__ (<class'__main__.ParentClass1'>,<class'__main__.ParentClass2'>).提示: 如果沒有指定基類,python的類會默認繼承object 類,object 是所有python類的基類,
他提供了一些常見方法(如 ( __str__ )的實現。
ParentClass1.__bases__ (<class 'object'>,) ParentClass2.__bases__ (<class 'object'>,)
繼承與抽象(先抽象在繼承)
抽象即抽取類似或者比較像的部分。
抽象分為兩個層次:
1.邱吉爾跟川普 兩對象比較像部分抽取成類。
2.將 人、貓、狗 這三個類比較像的部分抽取成父類。
抽取最主要的作用是劃分類別 (可以隔離關注點、降低複雜度)
抽象只是分析和設計的過程中,一個動作或者說一種技巧,通過抽象可以得到類
繼承例子與重用性
#實際運用例如 :
人會 吃、喝、看電視
猴子會 吃、喝、 爬樹
現在要為 人跟猴子 創建一個類,那麼就需要為 人 跟猴子 實現他們所有個功能,方式如下:
#人跟猴子 有像似的地方
class 人 :
def 吃(self):
# do something
def 喝(self):
# do something
def 看電視(self):
# do something
class 猴子 :
def 吃(self):
# do something
def 喝(self):
# do something
def 爬樹(self):
# do something
人 跟 猴子 都有相同的功能,可以使用 繼承 把相似的部分只要書寫一次就讓猴子跟人可以使用,更改後如下:
動物: 吃、喝
人 : 看電視(人繼承動物的功能)
猴子 : 爬樹(猴子繼承動物的功能)
轉化如下:
class 動物:
def 吃(self):
#do somthing
def 喝(self):
#do somthing
# 在類後面掛號中寫入另一個類名,表示當前類繼承另外一個類,如下:
class 人(動物):
def 看電視(self):
print ( '看新聞' )
class 猴子(動物):
def 爬樹(self):
print ( '摘香蕉' )
#繼承 的程序實現
class Animal: def eat(self): print("%s 吃"%self.name) def drink(self): print("%s 喝" % self.name) class People(Animal): def __init__(self,name): self.name = name self.breed = '人' def skill(self): print('看電視') class Monkey(Animal): def __init__(self,name): self.name = name self.breed = '猴子' def ability(self): print('爬樹') #調用 p1 = People('愛看新聞的上班族') p1.eat() p2 = People('愛看體育的年輕人') p2.drink() m1 = Monkey('愛吃香蕉的猴子') m1.eat()執行結果:
愛看新聞的上班族 吃
愛看體育的年輕人 喝
愛吃香蕉的猴子 吃
.在編成的過程中,如果我們定義了一個類A,然後又想建立另外一個類B,但是類B的大部分內容與類A的相同時,我們不可能從開始寫一個類B,這就用到了類的繼承概念!
通過繼承的方式新建類B,讓B繼承A,B會 "遺傳" A的所有屬性(數據屬性 和 函數屬性)
實現程序重用。
class Animal : # 人跟猴子都是動物,所以創建一個 Animal基類
def __init__(self,name,aggressivity, life_value): self.name = name # 人跟猴都有自己的暱稱
self.aggressivity = aggressivity
#人跟猴都有自己的攻擊力
self.life_value = life_value #人和猴都有自己的生命值 def eat(self): print('%s is eating'%self.name) class monkey (Animal): pass class people (Animal): pass egg = people('egon',10,1000) ha2 = monkey('阿猴子',50,1000) egg.eat() ha2.eat()執行結果:
egon is eating
阿猴子 is eating
.提示: 用已經有的類建立一個新的類,這樣就重用了已經有的軟體中的一部分設置大部分,大幅提升了編程工作量, 這就是常說的軟體重用, 不僅可以重用自己的類,也可以繼承別人的,比如標準庫, 來制定新的數據類型,這樣就能大大縮短了軟體開發週期,對大型軟體開發來說,意義重大。
派生
子類可以添加自己的新屬性或者在自己這裡重新定義這些屬性(不會引響到父類),須注意的是,一旦重新定義了自己的屬性且與父類相同重名,那麼調用新增的屬性時,就以自己為準。class Animal : # 人跟猴子都是動物,所以創建一個 Animal基類 def __init__(self,name,aggressivity, life_value): self.name = name # 人跟猴都有自己的暱稱 self.aggressivity = aggressivity #人跟猴都有自己的攻擊力 self.life_value = life_value #人和猴都有自己的生命值 def eat(self): print('%s is eating'%self.name) class monkey (Animal): #猴類,繼承Animal類 def skill(self,people): # 派生:猴子會攻擊人 # param people people.life_value -= self.aggressivity class people (Animal): # 人類,繼承Animal def attack(self,monkey): # 派生: 人有攻擊的能力 # param monkey monkey.life_value -= self.aggressivity egg = people('egon',10,1000) ha2 = monkey('吃香蕉',50,1000) print(ha2.life_value) print(egg.attack(ha2)) print(ha2.life_value)執行結果:
1000
None
990
.注意: 像 ha2.life_value 之類的的屬性引用,會先從實例中找life_value然後去類中找,然後再去父類找...直到最後找頂級的父類
在子類中,新建的重名的函數屬性,在編輯函數內功能的時候,有可能需要重用父類中重名的那個函數功能,應該適用調用普通函數的方式,即: 類名.func(),此時就與調用普通函樹無異了! 因此即便是 self 參數也須要傳值.
如子類要執行父類的方法也使用super方法: (適用於pytthon 3)
方法如下:
class A : def opop(self): print('A') class B(A): def opop(self): super().opop() #super(B.self).opop() #A.opop(self) print('B') a = A() b = B() b.opop() super(B,b).opop()執行結果:
A
B
A
class Animal: # 人跟猴 都是動物 所以創造一個Animal 基類 def __init__(self,name,aggressivity,life_value): self.name = name # 人跟猴 都有自己的暱稱 self.aggressivity =aggressivity #人和猴都有自己的攻擊力 self.life_value = life_value #人跟猴 都有自己的生命值 def eat(self): print('%s is eating'%self.name) class monkey(Animal): #猴類 繼承Animal類 def __init__(self,name,breed,aggressivity,life_value): super().__init__(name,aggressivity,life_value) #執行父類Animal self.bread = breed #派生出了新的屬性 def bite(self,pople): # 派生出新的技能: 猴子有咬人的技能 # param people pople.life_value -= self.aggressivity def eat(self): Animal.eat(self) print('from monkey') class Person(Animal): # 人類 繼承Animal def __init__(self,name,aggressivity, life_value,money): super().__init__(name,aggressivity,life_value) #執行父類 self.money = money #派生出了新的屬性 def attack(self,monkey): #派生出新的技能 : 人有攻擊的技能 #param monkey monkey.life_value -= self.aggressivity def eat(self): Animal.eat(self) print('from Person') egg = Person('egon',10,10000,600) ha2 = monkey('吃香蕉','哈士奇',10,1000) print(egg.name) print(ha2.name) egg.eat()
執行結果:
egon
吃香蕉
egon is eating
from Person
.通過繼承建立了派生類與基類之間的關係, 他是一種"是" 的關係,比如說 黑猴是猴,人是動物。當類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如老闆是上司
class Boss : def __init__(self,name,gender): self.name = name self.gender = gender def teach(self): print('teaching') class jobs(Boss): pass p1 = jobs('egon','male') p1.teach()執行結果:
teaching
下面就是一個簡單的繼承例子
class Parent: def hello(self): print("正在調用父類的方法.....") class Child(Parent): pass p = Parent() p.hello() c = Child() c.hello()執行結果:
正在調用父類的方法.....
正在調用父類的方法.....
.如果子類中定義與父類同名的方法或屬性,則會覆蓋父類對應的方法或屬性。
class Parent: def hello(self): print("正在調用父類的方法.....") class Child(Parent): pass class Child(Parent): def hello(self): print("正在調用子類的方法....") c= Child() c.hello() p=Parent() p.hello()執行結果:
正在調用子類的方法....
正在調用父類的方法.....
.以下是一個繼承的例子
import random as r class Fish: def __init__(self): self.x = r.randint(0,10) self.y = r.randint(0, 10) def move(self): self.x -= 1 print("我的位置是:",self.x,self.y) class Goldfish(Fish): pass class carp(Fish): pass class Salmon(Fish): pass class Shark(Fish): def __init__(self): self.hungry = True def eat(self): if self.hungry: print("吃貨的夢想就是天天有的吃....") self.hungry = False else: print("太撐了,吃不下了!") fish = Fish() fish.move() fish.move() goldfish =Goldfish() goldfish.move() goldfish.move() goldfish.move() shark = Shark() shark.eat() shark.eat()執行結果:
我的位置是: 5 0
我的位置是: 4 0
我的位置是: 2 10
我的位置是: 1 10
我的位置是: 0 10
吃貨的夢想就是天天有的吃....
太撐了,吃不下了!
.至時候如果再調用 shark.move() 就會抱錯
原因為:
#因父類被子類覆寫過所以報錯,解決方法有兩個#1.調用為幫定的父類方法#2.使用super函數(功能為:用于调用父类(超类)的一个方法)#super也可以用來解決多重繼承、重複調用等問題
import random as r class Fish: def __init__(self): self.x = r.randint(0,10) self.y = r.randint(0, 10) def move(self): self.x -= 1 print("我的位置是:",self.x,self.y) class Goldfish(Fish): pass class carp(Fish): pass class Salmon(Fish): pass class Shark(Fish): def __init__(self): self.hungry = True def eat(self): if self.hungry: print("吃貨的夢想就是天天有的吃....") self.hungry = False else: print("太撐了,吃不下了!") fish = Fish() fish.move() fish.move() goldfish =Goldfish() goldfish.move() goldfish.move() goldfish.move() shark = Shark() shark.eat() shark.eat() shark.move() #在一次調用執行結果:
Traceback (most recent call last):
我的位置是: 1 7
我的位置是: 0 7
我的位置是: 1 8
File "D:/python t11/fish.py", line 44, in <module>
我的位置是: 0 8
我的位置是: -1 8
吃貨的夢想就是天天有的吃....
太撐了,吃不下了!
shark.move() #在一次調用
File "D:/python t11/fish.py", line 10, in move
self.x -= 1
AttributeError: 'Shark' object has no attribute 'x'
.下面是修改的方法
1.重新調用父類方法
import random as r class Fish: def __init__(self): self.x = r.randint(0,10) self.y = r.randint(0, 10) def move(self): self.x -= 1 print("我的位置是:",self.x,self.y) class Goldfish(Fish): pass class carp(Fish): pass class Salmon(Fish): pass class Shark(Fish): def __init__(self): Fish.__init__(self) #寫上父類的名子 self.hungry = True def eat(self): if self.hungry: print("吃貨的夢想就是天天有的吃....") self.hungry = False else: print("太撐了,吃不下了!") fish = Fish() fish.move() fish.move() goldfish =Goldfish() goldfish.move() goldfish.move() goldfish.move() shark = Shark() shark.eat() shark.eat() shark.move() #在一次調用shark = Shark() #修改後再次引用shark.move()執行結果:
我的位置是: 4 3
我的位置是: 3 3
我的位置是: 5 1
我的位置是: 4 1
我的位置是: 3 1
吃貨的夢想就是天天有的吃....
太撐了,吃不下了!
我的位置是: 2 6
我的位置是: 5 3
2.使用 shark.move()
import random as r class Fish: def __init__(self): self.x = r.randint(0,10) self.y = r.randint(0, 10) def move(self): self.x -= 1 print("我的位置是:",self.x,self.y) class Goldfish(Fish): pass class carp(Fish): pass class Salmon(Fish): pass class Shark(Fish): def __init__(self): super().__init__() #使用 super函數 self.hungry = True def eat(self): if self.hungry: print("吃貨的夢想就是天天有的吃....") self.hungry = False else: print("太撐了,吃不下了!") fish = Fish() fish.move() fish.move() goldfish =Goldfish() goldfish.move() goldfish.move() goldfish.move() shark = Shark() shark.eat() shark.eat() shark = Shark() #已用super函數 修改shark.move()執行結果:
我的位置是: 6 4
我的位置是: 5 4
我的位置是: -1 4
我的位置是: -2 4
我的位置是: -3 4
吃貨的夢想就是天天有的吃....
太撐了,吃不下了!
我的位置是: 8 3
.python 也可以多重繼承 class className(Base1,Base2,Base3): .....
class Base1: def f1(self): print("我是f1,我為Base1代言...") class Base2: def f2(self): print("我是f2,我為Base2代言...") class C(Base1,Base2): pass c = C() c.f1() c.f2()執行結果:
我是f1,我為Base1代言...
我是f2,我為Base2代言...
沒有留言:
張貼留言