1、上節補充
一、靜態屬性
靜態屬性 : 類的屬性,全部的對象共享這個變量
若是用對象名去修改類的靜態屬性:在對象的空間中又建立了一個屬性,而不能修改類中屬性的值
操做靜態屬性應該用類名來操做java
例1:請你寫一個類,可以統計一共實例化了多少個對象?python
class Foo: count = 0 def __init__(self): Foo.count += 1 f1 = Foo() print(f1.count) # 1 f2 = Foo() f3 = Foo() f4 = Foo() f5 = Foo() print(f1.count) # 5 print(f5.count) # 5 print(Foo.count) # 5
結論:當類中的屬性發生改變的時候,對象中沒有同名的屬性、方法的時候,對象使用屬性名會跟着類中的變量走算法
例二:(類的靜態屬性爲可變數據類型,對象也能引用並修改)編程
class Foo: count = [0] f1 = Foo() f1.count[0] += 1 # 靜態屬性的修改 1 print(f1.count[0]) # 對象引用類的靜態屬性 1 print(Foo.count[0]) # 類修改後 也是 1 f1.count = [2] # 對象新增 2 print(f1.count) # 2 print(Foo.count) # 類不變 1
結論:
1,類的靜態屬性是可變數據類型時,對象能夠引用並修改
2,只要對象的某個屬性被直接賦值,那麼必定是對象的命名空間發生變化
3,只要是靜態變量,就用類名操做python3.x
(面向對象的三大特性:繼承、多態、封裝,這裏先說一下繼承)
2、繼承(提升代碼的重用性,規範性)微信
(C語言沒有面向對象,而java和C#只有單繼承沒有多繼承(可是有接口),
python和C++有單繼承也有多繼承(python本來並無接口,可是有些人爲python開發了接口模塊,因此在python中,
須要用接口的時候要安裝特定的模塊))函數
2-1單繼承:
1,語法:
class A:
passpost
class B(A):
pass微信支付
這就是單繼承:
A就叫:父類/超類/基類
B就叫:子類/派生類this
2,繼承與重用:子類可使用父類中的變量和方法
下面看個例子瞭解一下:
咱們都知道貓有本身的名字和吃的糧食,還有貓會喝水吃東西,抓老鼠等,
狗也有本身的名字和吃的糧食,狗也會喝水吃東西,狗還能看家等。
所以構建出來的類以下:
class Cat(): def __init__(self,name,food): self.name = name self.food = food def eat(self): print('吃貓糧') def drink(self): print('喝水') def catch_mouse(self): print('抓老鼠') class Dog(): def __init__(self,name,food): self.name = name self.food = food def eat(self): print('吃狗糧') def drink(self): print('喝水') def look_after_house(self): print('看家') xiaomao = Cat('啊貓','貓糧') print(xiaomao.name) #啊貓 xiaomao.eat() #吃貓糧 xiaomao.catch_mouse() #抓老鼠 xiaogou = Dog('啊狗','狗糧') print(xiaogou.name) #啊狗 xiaogou.eat() #吃狗糧 xiaogou.look_after_house() #看家
這麼一看是否是感受代碼有不少重複的地方,好比初始化名字和食物、吃東西和喝水的方法,
那麼怎麼樣能夠節省代碼呢?這就要用到繼承。
咱們先定義一個公共的類Animal,用來存儲貓和狗相同的方法和屬性。貓類和狗類分別繼承Animal類,
就能夠繼承Animal的屬性和方法了。
class Animal: def __init__(self,name,food): self.name = name self.food = food def eat(self): print('吃%s'%(self.food)) def drink(self): print('喝水') class Cat(Animal): def catch_mouse(self): print('抓老鼠') class Dog(Animal): def look_after_house(self): print('看家') xiaomao = Cat('啊貓','貓糧') print(xiaomao.name) #啊貓 xiaomao.eat() #吃貓糧 xiaomao.catch_mouse() #抓老鼠 xiaogou = Dog('啊狗','狗糧') print(xiaogou.name) #啊狗 xiaogou.eat() #吃狗糧 xiaogou.look_after_house() #看家
這樣一來是否是就簡化了不少,並且再來一個豬類,只要它也是有這些公共方法,它也能繼承Animal類,
一會兒就能夠節省了不少代碼。
其中:
父類/超類/基類 :Animal
子類/派生類 :Cat、Dog
3,繼承與派生:
(1)繼承:提升代碼的重用性,規範代碼
(2)派生:子類在父類的基礎上又新建立了本身須要的方法和屬性
(3)父類有的而子類沒有:子類對象直接調用 就會直接執行父類的方法
(4)父類有的而子類也有:一、子類對象調用 直接執行子類中的方法
二、想在子類中使用父類的名字:父類名、super()去調用
例如:
class Animal: def __init__(self, name, food): self.name = name self.food = food def eat(self): print('吃%s' % (self.food)) def drink(self): print('喝水') class Cat(Animal): # Animal的派生類 def __init__(self, name, food, eye_color): self.eye_color = eye_color # 派生屬性 super().__init__(name, food) # Animal.__init__(self,name,food) 跟上一句super()都是調用父類的方法 # 不一樣的是super()不須要傳self,而直接用父類名.方法(),須要傳self def catch_mouse(self): # 派生方法 print('抓老鼠') def eat(self): # 不只執行了父類中的基礎功能,還完成了特殊的功能 Animal.eat(self) # super().eat() self.weight = 10 class Dog(Animal): def look_after_house(self): print('看家') def eat(self): # Animal.eat(self) super().eat() self.drink() # 吃完東西調用父類喝水的方法 xiaomao = Cat('阿貓', '貓糧', '綠色') print(xiaomao.eye_color) # 綠色 print(xiaomao.food) #貓糧 xiaomao.catch_mouse() #抓老鼠 xiaomao.eat() #吃貓糧 print(xiaomao.weight) # 10 xiaogou = Dog('啊狗', '狗糧') xiaogou.eat() #吃狗糧 喝水
2-2多繼承:
1,語法:
class A:
pass
class B:
pass
class C(A,B):
pass
C既繼承了A,又繼承了B
2,實例:
# 天鵝:飛 游泳 走路 # 老虎:走路 游泳 # 鸚鵡:飛 說話 走路 class Animal: def __init__(self,name): self.name = name class FlyAnimal(Animal): #會飛的動物類 def fly(self): print('%s在飛' % self.name) class WalkAnimal(Animal): #會走路的動物類 def walk(self): print('%s在走路'%self.name) class SwimAnimal(Animal): #會游泳的動物類 def swim(self): print('%s在游泳'%self.name) class Tiger(SwimAnimal,WalkAnimal): # 老虎 pass class Swan(SwimAnimal,WalkAnimal,FlyAnimal): # 天鵝 pass class Parrot(FlyAnimal,WalkAnimal): # 鸚鵡 def talk(self): print('%s說話了'%self.name) swan = Swan('天鵝') swan.fly() # 天鵝在飛 swan.walk() # 天鵝在走路
3、抽象類:抽象類是一個規範,它基本不會實現什麼具體的功能,只能被繼承,不能被實例化
一、抽象類的做用:規範編程模式
多人開發、複雜的需求、後期的擴展
是一種用來幫助咱們完成規範化的手段
二、如何定義抽象類
1,from abc import ABCMeta,abstractmethod
2,在這個類建立的時候指定 metaclass = ABCMeta
3,在你但願子類要實現的方法的上一行加上一個 @abstractmethod裝飾器
三、使用抽象類
1,繼承這個類
2,必須實現這個類中被@abstractmethod裝飾器裝飾的方法
四、實例
# 支付功能 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): # 模板的功能 @abstractmethod # abstractmethod是一個裝飾器,裝飾器怎麼用?放在函數或者類的上一行 def pay(self): pass # 這樣就構建了一個抽象類Payment,並聲明瞭子類必需要實現的方法是 pay(),若子類沒有定義pay(),則實例化時會報錯 class Alipay(Payment): # 繼承了抽象類,就必須實現抽象類中被@abstractmethod裝飾器裝飾的方法 pay() def pay(self, money): print('使用支付寶支付了%s元' % money) class Wechatpay(Payment): def pay(self, money): print('使用微信支付了%s元' % money) class My_pay(Payment): # 這裏沒有定義pay()方法,那麼在實例化的時候機會報錯 def fuqian(self,money): print('你支付了%s元' % money) def pay(obj, money): obj.pay(money) # p = Payment() # 報錯 抽象類不能被實例化 a = Alipay() # a.pay(100) pay(a,100) # 使用支付寶支付了100元 we = Wechatpay() # we.pay(200) pay(we,200) # 使用微信支付了200元 my = My_pay() # 報錯:類中沒有定義抽象類的pay方法 pay(my,300)
4、新式類
一、新式類和經典類:
繼承了object的類就是新式類
在py3中默認都繼承了object所以全部的類都是新式類
在py2中既有新式類又有經典類
python3.x:
在python3.x版本中全部的類都是新式類
全部的新式類都有一個默認的父類 : object
class Person1:pass
class Person2():pass
class Person3(object):pass
# __bases__方法是查看某個類繼承的全部父類
print(Person1.__bases__) # (<class 'object'>,)
print(Person2.__bases__) # (<class 'object'>,)
print(Person3.__bases__) # (<class 'object'>,)
python 2.7:
經典類和新式類並存
class Student:pass # 經典類
class Student(object):pass # 新式類
class Person1:pass # 經典類
class Person2():pass #經典類
class Person3(object):pass #新式類
二、多繼承的順序(在新式類和經典類之間的區別)
新式類
全部的多繼承關係尋找方法的順序 :遵循廣度優先算法
繼承object
類名.mro() # (返回一個類的尋找順序(繼承順序)的列表)
super : super不是單純的找父類,而是遵循mro順序的
經典類
python2.x
不主動繼承object
經典類在找父類中方法的過程當中遵循:深度優先算法
不提供mro方法和super
2-一、新式類中
class A: def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] D().func() # A C B D
class A: pass class B(A): pass class C(A): pass class D(B): pass class E(C): pass class F(D,E): pass print(F.mro()) 結果: # [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>,
<class '__main__.A'>, <class 'object'>]