1.當類之間有顯著的不一樣,而且較小的類是較大的類所須要的組件時,用組合較好python
''' 1.組合:在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合 ''' class School: def __init__(self,name,add): self.name=name self.add=add class Course: def __init__(self,name,price,priod,school): self.name=name self.price=price self.priod=priod self.school=school #傳入一個類,這樣就構成了一個組合,一類中包含了另外一個類 s1=School('清華','北京') s2=School('科大','合肥') c1=Course('python','1w','3mon',s1) #這就是組合,大類中包含小類 c2=Course('linux','2w','4mon',s2) print(c1.school.name) print(s1,'\n',c1.__dict__['school'])#打印 s1內存地址,地址相同
2.當類之間有許多共同的功能,提取這些共同的功能作基類,用繼承較好linux
繼承:具備兩方面含義,一是繼承父類的特性,二是具備本身衍生的特性ide
單繼承:從上往下繼承,先繼承祖先類,再繼承子孫類的類數據屬性和方法屬性,實例化時,先查找本身的__init__方法,沒有再往上找,直到找到爲止,工具
若是都沒有顯示的__init__方法,調用object類的__init__方法spa
class A: print('---A---') def __init__(self,name): self.name=name print('A:name=%s'%self.name) def eat(self): print('%s正在吃ing'%self.name) class B(A): a=1 print('---B---') class C(B): print('---C---') def __init__(self,sex,age): self.g=super().__init__('小a') self.sex=sex self.age=age print('C:sex=%s age=%s'%(sex,age)) c=C('boy',50)#先打印 B C類的數據屬性,至關於先將打印的代碼加載到C類中,再調用父類的__init__,最後是自身的__init__方法 c.eat()#小a正在吃ing print(c.__dict__)#{'name': '小a', 'g': None, 'sex': 'boy', 'age': 50},擁有了name數據屬性
多繼承:根據mro線性順序表繼承(廣度優先查找),一樣先繼承全部父類的數據屬性,再查找__init__,調用了哪一個父類的__init__方法,就繼承了該父類的全部其它方法屬性,未被調用的父類,則不繼承該父類的方法屬性。3d
''' 1.組合:在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合 ''' class School: def __init__(self,name,add): self.name=name self.add=add class Course: def __init__(self,name,price,priod,school): self.name=name self.price=price self.priod=priod self.school=school #傳入一個類,這樣就構成了一個組合,一類中包含了另外一個類 s1=School('清華','北京') s2=School('科大','合肥') c1=Course('python','1w','3mon',s1) #這就是組合,大類中包含小類 c2=Course('linux','2w','4mon',s2) print(c1.school.name) print(s1,'\n',c1.__dict__['school'])#打印 s1內存地址,地址相同 ''' 2. 繼承:新建的類能夠繼承一個或多個父類,父類又可稱爲基類或超類,新建的類稱爲派生類或子類 python中類的繼承分爲:單繼承和多繼承 ''' class Father: money=100 #繼承類的屬性和方法 def __init__(self,name): self.name=name print('這是爸爸【name=%s】類'%self.name) def Habit(self): print('爸爸【name=%s】的壞習性:愛抽菸'%self.name) def work(self): print('Father教學生') class Mother: car='路虎' def __init__(self,age,national ): self.age=age self.national=national print('這是媽媽【age=%d】類'%self.age) def Hobby(self): print('媽媽【age=%d】的愛好是打球'%self.age) class Son(Father,Mother): #能夠多繼承,但實例化時,若自身沒有__init__,則調用第一個父類的__init__,即Father.__init__ def work(self): print('Son開汽車') print(Father.__dict__) print(Mother.__dict__) print(Son.__dict__) #不包含父母類的任何屬性{'__module__': '__main__', 'work': <function Son.work at 0x000000000225A0D0>, '__doc__': None} f=Father('大明')#建立Father對象,調用__init__實例化一個f對象,返回:這是爸爸【name=大明】類 m=Mother(30,'美國人')# 這是媽媽【age=30】類 print(Son.__base__)#__base__只查看從左到右繼承的第一個父類,<class '__main__.Father'> print(Son.__bases__)#__bases__,查看全部父類,(<class '__main__.Father'>, <class '__main__.Mother'>) s=Son('小明')#先調用本身的__init__,沒有則調用繼承的第一個父類,Father.__init__實例化一個s對象,故返回:這是爸爸【name=小明】類, print(s.name,s.car,s.money)#能調用父母類的靜態數據屬性,小明 路虎 100 s.Habit()#能調用父類的方法屬性,爸爸【name=小明】的壞習性:愛抽菸 s.work()#Son開汽車---->方法名相同,並不會改寫父類的方法, f.work()#Father教學生---->父類方法不變 s.Hobby()#出錯,AttributeError: 'Son' object has no attribute 'age',由於實例化時調用的是第一個父類Father.__init_
class Grandpa: language='英語' def tell(self): print('Grandpa會講%s'%self.language) class Son1(Grandpa,Mother): def job(self): print('Son1 is a driver') s1=Son1(15,'中國') s1.Hobby()#這是媽媽【age=15】類,媽媽【age=15】的愛好是打球,Grandpa類沒有.__init__,就調用Mother.__init__ print(Son1.mro())#繼承順序:[<class '__main__.Son1'>, <class '__main__.Grandpa'>, <class '__main__.Mother'>, <class 'object'>]
總結:類中的方法屬性都是與具體對象綁定的,而數據屬性無具體對象綁定,因此,在多繼承中,只有實例化了父類,即調用了父類的__init__方法後,才能調用該父類的其它方法屬性,而沒 有被實例化的父類,則不會繼承其方法屬性,但具備其數據屬性。至於@staticmethod的類工具包,既不綁定類又不綁定對象的方法屬性,是能繼承的。@classmethod,類方法,也是被類繼承。code