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) # 鴨子型別(沒有繼承)
複製程式碼