python物件導向[基礎]

一個胖子啊發表於2019-04-13

1.類成員

1.類變數
  • 類的成員變數描述物件的屬性值根據物件不同會產生區別,此時類變數稱為例項變數
  • 類變數的成員變數描述物件的屬性值根據物件的不同不會產生區別,稱此類變數為類變數
  • 類變數是歸屬類的,例項變數是歸屬物件的
  • 類變數書寫在類定義的裡面,例項變數書寫在__init__方法中
class Dog:
    var = "都是狗"  #類變數 定義在類裡
    # 所以的物件都有這個變數值
    def __init__(self, name, age):  # 物件變數 定義在init裡
        self.name = name
        self.age = age
# 類名.變數名 方式訪問類變數
# 類名.變數名 = 變數值  方式修改
複製程式碼
類變數名的訪問

1.類名.類變數名(推薦)

2.物件名.類變數名

類變數名的修改

類名.類變數名 = 變數值

不允許使用 物件名.類變數名 = 變數名修改 這樣會給該變宣告一個獨有屬性 僅修改該物件的屬性值

類變數可以私有化

作用:記錄建立了多少個物件 +=1

記錄一個總數 每個方法都能呼叫 且通用

2.類方法

定義格式:

在類方法中,類屬性訪問可以通過 cls.類屬性名 來訪問

class 類名:
    @classmethod
    def 方法名(cls, 形參):
        方法體
複製程式碼

呼叫格式:

類名.方法名(實參) (推薦) 物件名.方法名(實參) (不推薦)

如果類方法和成員方法名字衝突時,不能使用 物件名.方法名(實參) 呼叫方法,這樣會呼叫寫在後面的方法,

通過cls(變數名)可以建立一個物件

只要方法名稱相同(無論修飾符是否一樣) 就會出現覆蓋的情況 後面寫的會被呼叫

注意:類方法和成員方法之間的相互呼叫

類方法中不允許使用例項變數和例項方法

例項方法中允許使用類變數和類方法,推薦使用類名呼叫

class Dog:
    var = "都是狗"  #類變數 定義在類裡
    def __init__(self, name, age):  # 物件變數 定義在init裡
        self.name = name
        self.age = age
    @classmethod   # 定義一個類方法
    def show_me(cls):
        print("類方法的狗子") 
        # slef.show    成員方法無法呼叫類方法和類變數

    def show(self):  # 定義一個成員方法
        print(Dog.var) # 類方法可以定義成員變數
        Dog.show_me()  #類方法可以呼叫成員方法
        print("成員方法的狗子")
dog1 = Dog("狗子", 18)
dog1.var = "不是狗"
print(dog1.var)
dog1.show()
複製程式碼
  • 注意:self 和cls的自動補充:

    ​ 這只是一個變數名而已,自動補充的 可以用任何變數名代替

  • 靜態方法(瞭解 不常用)
    @staticmethod  # 靜態方法的建立
    def show1():
        print("一個靜態方法")
    複製程式碼

    呼叫方法:

    類名.方法名(實參) (推薦)

    物件名.方法名(實參) (不推薦)

    靜態方法的定義與類無關,與物件無關,可以轉化成函式定義

    用途:用於存放工具類,使其存放在一起,類名.即可看到

3.物件導向名稱的總結

  • 公有變數:類中 有self.字首的變數都是公有變數
  • 全域性變數:在檔案的最外層,或者在函式中加了global的變數
  • 區域性變數:定義在函式中的,類中的方法裡,成員變數名沒有self的也是區域性變數
  • 獨有變數:只有這一個物件才有的變數,
  • 私有變數:類變數名前有2個下劃線__的稱為私有變數,只能在類的內部使用
  • 類變數:定義在類的下邊,沒有在方法裡面
  • 成員變數 = 公有變數
  • ______init__方法:構造方法
  • 物件 可以稱為例項

5.2繼承

1.基礎格式:

​ class 子類名稱(父類名稱):

​ pass

繼承描述的是一種類間關係,一個類從另一個類獲取成員資訊的類間關係。

繼承作用:繼承父類的變數和方法;子類可以新增父類沒有的東西,父類私有成員不可以被繼承

2.繼承的關係結構圖

  • object是所有類的父類

檢視繼承關係結構:類名.mro

class Anmail:
    pass
class Cat(Anmail):  #Anmail是cat的父類
    pass
class SmallCat(Cat):  # Cat是smallcat的父類
    pass
print(SmallCat.__mro__)
# 此時輸出:(<class '__main__.SmallCat'>, <class '__main__.Cat'>, <class '__main__.Anmail'>, <class 'object'>)
# 即  object是Anmail的父類,Anmail是Cat的父類,Cat是SmallCat的父類
複製程式碼

3.重寫

子類重寫了__init__時,例項化子類,就不會呼叫父類已經定義的__init__,即被重寫

  • 在子類中可以定義與父類相同名稱的方法,此時子類的方法對父類的方法構成了重寫。 如果子類重寫了父類的方法,使用子類物件呼叫被重寫的方法時,執行子類中重寫後的方法

__str__方法就是一個重寫

呼叫父類被重寫的方法:

​ 1 父類名.init(self,引數)#注意名字是父類

​ 2 super(子類名,self).init(引數)#注意名字是子類,而且init後是se1f之外的引數

​ 呼叫格式一:父類名.方法名(物件)

​ 呼叫格式二:super(本類名,物件).方法名()

​ 呼叫格式三:super().方法名() (推薦)

重寫後 父類和子類的資訊都會有 而不是覆蓋

class People:
    def __init__(self, age):
        self.name = None
        self.age = age
    def said(self):
        print("父類說")
class Man(People):
    def __init__(self):
        super().__init__(None)  # 子類重寫時如何呼叫父類的成員變數? 引數不能寫變數嗎?
        self.sex = "man"
    def said(self):
        print("子類說")
        super().said()
people1 = People(18)
print(people1.age)
man1 = Man()
print(man1.age)
複製程式碼

init方法中,子類要重新父類init時,父類傳遞了引數,子類也需要傳參

class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age

class Teacher(Person):
    def __init__(self,name,age): 父類有
        super().__init__(name,age)
        self.id = "111"
複製程式碼

4.多繼承

格式: class 子類名(父類名1,父類名2,父類名3):

​ pass

如果方法,變數有衝突,則先選擇寫在前面的父類

重寫:父類名.方法名(self)

​ 如果寫super().方法名(),則預設呼叫寫在前面的父類名方法(父類名1)

需要檢視具體重寫的那個方法 同樣用:類名.___ __mro _

5.多型

同一個物件,在不同的使用環境中以不同的形態展示其功能,稱該物件具有多型特徵

​ 多型發生在繼承關係的基礎之上

# 同一個物件,在不同的使用環境中以不同的形態展示其功能,稱該物件具有多型特徵。
class Eat:
    def breakfast(self):
        print("吃飯")
class Sleep:
    def bed(self):
        print("睡覺")
class Man(Eat,Sleep):
    def breakfast(self):
        print("吃早飯呢")
    def bed(self):
        print("在床上睡覺")
class Demo:
    def test(self,who):
        who.breakfast()
eat1 = Eat()
man1 =Man()  # 以多型的形式展現出來 需要eat  但是給了一個具有eat方法的子物件也行
demo1 = Demo()
demo1.test(man1)
複製程式碼
鴨子型別

物件在語法層面滿足呼叫關係,實際不具有對應的物件形態,稱該物件此時具備鴨子型別

鴨子型別是一種特殊的多型表現形式 鴨子型別和多型就差了一個繼承

class Eat:
    def rice(self):
        print("吃米飯")
class Paly:
    def player(self):
        print("玩遊戲")
class Man(Eat,Paly):  # 子類
    def rice(self):
        print("吃好吃的米飯")
    def player(self):
        print("玩好玩的遊戲")
class Stdent:  # 沒有關係的類
    def rice(self):
        print("學生也不吃飯")
    def play(self):
        print("好學生不玩遊戲")
class Demo:
    def demo1(self,who):
        who.rice()
demo = Demo()
man =Man()
std1 = Stdent()
demo.demo1(man)  # 繼承
demo.demo1(std1) # 鴨子型別(沒有繼承)
複製程式碼

相關文章