python高級-面向對象特性(12)

1、繼承的概念

在現實生活中,繼承通常指的是子女繼承父輩的財產,在程序中,繼承描述的是事物之間的所屬關係,例如貓和狗都屬於動物,程序中即可以描述爲貓和狗繼承自動物;同理,波斯貓和巴釐貓都繼承自貓,而沙皮狗和斑點狗都繼承足夠,以下如所示:python

 

2、繼承的示例

class Cat(object): def __init__(self,name,color="白色"): self.name = name self.color = color def run(self): print("%s:在跑"%self.name) class Bosi(Cat): def setNewName(self,newName): self.name = newName def eat(self): print("%s:在吃"%self.name) bs = Bosi("波斯貓") print("bs的名字是:%s,顏色是:%s"%(bs.name,bs.color)) bs.eat() bs.setNewName("湯姆貓") bs.run()

運行結果爲:安全

bs的名字是:波斯貓,顏色是:白色
波斯貓:在吃
湯姆貓:在跑

說明:spa

  • 雖然子類沒有定義__init__()方法,可是父類有。因此在子類集成父類的時候這個方法就被繼承了,因此只要建立Bosi的對象,就默認執行了那個繼承過來的__init__()方法
  • 子類在繼承的時候,在定義類時,小括號()中爲父類的名字
  • 父類的全部非私有的屬性、方法、會被繼承給子類

注意:3d

  • 私有的屬性,不能經過對象直接訪問,可是能夠經過方法訪問
  • 私有的方法,不能經過對象直接訪問
  • 私有的屬性、方法,不會被子類繼承,也不能被訪問
  • 通常狀況下,私有的屬性、方法都是不對外公佈的,每每用來作內部的事情,起到安全的做用
class Animal(object): def __init__(self, name = "動物",color = "白色"): self.__name = name self.color = color def __test1(self): print(self.__name) print(self.color) def test2(self): print(self.__name) print(self.color) class Dog(Animal): def dogTest1(self): #不能訪問父類的私有屬性:AttributeError: 'Animal' object has no attribute '__name' #print(self.__name) print(self.color) def dogTest2(self): #self.__test1() self.test2() A = Animal() #print(A.__name) print(A.color) #不能訪問父類的私有方法:AttributeError: 'Animal' object has no attribute '__test1' #A.__test1() A.test2() print("-----------------分割線-----------------") D = Dog(name="阿黃",color = "黃色") D.dogTest1() D.dogTest2()

運行結果爲:code

白色 動物 白色 -----------------分割線----------------- 黃色 阿黃 黃色

 

3、多繼承

從圖中可以看出,所謂多繼承,即子類有多個父類,而且具備它們的特徵對象

Python中多繼承的格式以下:blog

class A: def printA(self): print("---A---") class B: def printB(self): print("---B---") #定義一個子類繼承A,B class C(A,B): def printC(self): print("---C---") obj_C = C() obj_C.printA() obj_C.printB()

運行結果爲:繼承

---A---
---B---

說明

  • python中是能夠多繼承的
  • 父類中的方法、屬性,子類會繼承
  • 若是多個父類中有同一個方法,誰寫在前面就調用誰的方法
class A: def printA(self): print("---A---") class B: def printB(self): print("---B---") #定義一個子類繼承A,B class C(A,B): def printC(self): print("---C---") obj_C = C() obj_C.printA() obj_C.printB() #能夠查看一個雷的對象搜索方法時的前後順序 print(C.__mro__)

運行結果爲:內存

---A---
---B--- (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

 

4、重寫父類方法與調用父類方法

一、重寫父類方法get

所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中同名的方法

 

class Cat(object): def sayHello(self): print("Hello:Cat") class Bosi(Cat): def sayHello(self): print("Hello:Bosi") bs = Bosi() bs.sayHello()

 

運行結果爲:Hello:Bosi

二、調用父類方法

class Cat(object): def __init__(self,name): self.name = name self.color = "黃色"

    

class Bosi(Cat): def __init__(self,name): #Cat.__init__(self,name) #python2的語法 #調用父類的方法 super().__init__(name) def getName(self): return self.name pass bs = Bosi("波斯") print(bs.name) print(bs.color)

運行結果爲:

波斯
黃色

 

5、多態

  • 多態的概念是應用於Java和C#這一類強類型語言中
  • 所謂多態:定義時的類型和運行時的類型不同,此時就成爲多態
class F1(object): def show(self): print("F1.show") class S1(F1): def show(self): print("S1.show") class S2(object): def show(self): print("S2.show") def func(obj): obj.show() s1_obj = S1() func(s1_obj) s2_obj = S2() func(s2_obj)

運行結果爲:S1.show、S2.show

 

6、類屬性、實例屬性

瞭解類基本的東西以後,下面看一下python中這幾個概念的區別、

在前面的例子中咱們接觸到的就是實例屬性(對象屬性),類屬性就是類對象所擁有的屬性,它被全部類對象的實例對象所共有,在內存中只存在一個副本,這個和C++中類的靜態成員變量有點相似。對於公有的類屬性,在類外能夠經過類對象和實例對象訪問

一、類屬性

class Person(object): name = "Tom" #公有的類屬性
    __age = 12   #私有的類屬性
 p = Person() print(p.name)        #正確
print(Person.name)   #正確
        
#print(p.__age) #錯誤,不能再類外經過實例變量訪問類的私有屬性 #print(Person.__age) #錯誤,不能再類外經過類對象訪問類的私有屬性

運行結果爲:Tom、Tom

二、實例屬性(對象屬性)

class Person(object): address = "廣州"
    def __init__(self): self.name = "Se7eN_HOU" self.age = 29 p = Person() p.age = 18 #實例屬性
print(p.name)    #正確
print(p.address) #正確。實例對象能夠訪問類屬性
print(p.age)     #正確

     
print(Person.address)   #正確 #print(Person.name) #錯誤,類不能訪問實例屬性 #print(Person.age) #錯誤,類不能訪問實例屬性

運行結果爲:

Se7eN_HOU 廣州 18 廣州

三、經過實例去修改類屬性

class Person(object): address = "廣州" #類屬性
 p = Person() print(p.address)    #正確
print(Person.address) #正確

print("-------分界線--------") p.address = "北京"
print(p.address) print(Person.address) print("-------分界線--------") Person.address = "上海"
print(p.address) print(Person.address)

運行結果爲:

廣州 廣州 -------分界線-------- 北京 廣州 -------分界線-------- 北京 上海

說明:

  • 若是須要在類外修改類屬性,必須經過類對象去引用而後進行修改。
  • 若是經過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性。
  • 若是經過實例對象去引用該類的類的屬性,實例屬性其實會從新建立一個新的屬性。

 

7、類方法

類方法:是類對象所擁有的方法,須要用修飾器@classmethod來標識其爲類方法,對於類方法,第一個參數必須是類對象,通常以cls做爲第一個參數(固然能夠用其餘名稱的變量做爲其第一個參數,可是大部分人都習慣以’cls’做爲第一個參數的名字,就最好用’cls’了),可以經過實例對象和類對象去訪問。

class Person(object): country = "china" @classmethod def getCountry(cls): return cls.country p = Person() print(p.getCountry()) #正確,實例對象能夠調用類方法
print(Person.getCountry())

運行結果爲:china、china

類方法還有一個用途就是能夠對類屬性進行修改:

class Person(object): country = "china" @classmethod def getCountry(cls): return cls.country @classmethod def setCountry(cls,newCountry): cls.country = newCountry p = Person() print(p.getCountry()) #正確,實例對象能夠調用類方法
print(Person.getCountry()) p.setCountry("CHINA") print(p.getCountry()) Person.setCountry("中國") print(Person.getCountry())

運行結果爲:

china
china
CHINA
中國

結果顯示在用類方法對類屬性修改以後,經過類對象和實例對象訪問都發生了改變

 

8、靜態方法

靜態方法:須要經過修飾器@staticmethod來進行修飾,靜態方法不須要多定義參數

class Person(object): country = "china" @staticmethod def getCountry(): return Person.country p = Person() print(p.getCountry()) print(Person.getCountry())

運行結果爲:china、china

總結:

實例方法:

  • 定義:第一個參數必須是實例對象,該參數名通常約定爲「self」,經過它來傳遞實例的屬性和方法(也能夠傳類的屬性和方法);
  • 調用:只能由實例對象調用。

類方法:

  • 定義:使用裝飾器@classmethod。
  • 第一個參數必須是當前類對象,該參數名通常約定爲「cls」,經過它來傳遞類的屬性和方法(不能傳實例的屬性和方法);
  • 調用:實例對象和類對象均可以調用。

靜態方法:

  • 定義:使用裝飾器@staticmethod。參數隨意,沒有「self」和「cls」參數,可是方法體中不能使用類或實例的任何屬性和方法;
  • 調用:實例對象和類對象均可以調用。
相關文章
相關標籤/搜索