python的面向對象 面向對象與面向過程 面向過程 面向過程思想:需要實現一個功能的時候,看重的是開發的步驟和過程,每一個步驟都需要自己親力親為,需要自己編寫代碼(自己來做) 面向對象 面向對象的三大特征:封裝性、繼承性、多態性 面向對象思想:需要實現一個功能的時候,看重的並不是過程和步驟,而是關 ...
python的面向對象
面向對象與面向過程
面向過程
- 面向過程思想:需要實現一個功能的時候,看重的是開發的步驟和過程,每一個步驟都需要自己親力親為,需要自己編寫代碼(自己來做)
面向對象
- 面向對象的三大特征:封裝性、繼承性、多態性
- 面向對象思想:需要實現一個功能的時候,看重的並不是過程和步驟,而是關心誰幫我做這件事(偷懶,找人幫我做)
類與對象
- 對象是面向對象編程的核心,在使用對象的過程中,為了將具有共同特征和行為的一組對象抽象定義,提出了另一個新的概念——類
- 類:抽象的,是一張“手機設計圖”
- 對象:具體的,是一個“真正的手機實例”
- 類是抽象的,在使用的時候通常會找到這個類的一個具體的存在;一個類可以找到多個對象
#學生案例
class Student(): #創建一個學生類
#定義一個info函數,並傳參至self本身
def info(self,name,age,sex):
print('學生的姓名是:',self.name)
print('學生的年齡是:',self.age)
print('學生的性別是:',self.sex)
yinianji = Student() #創建一個具體的對象:一年級
yinianji.info() #實例化對象調用定義的info函數
案例
當創建一個對象時,就是用一個模子來製造一個實物
#案例
class Dog(): #定義一個類的形式
#info是一個實例方法,類對象可以調用實例方法,實例方法的第一個參數一定是self
def info(self):
#當對象調用實例化方法時,python會自動將對象本身的引用作為參數,傳遞到實例方法的第一個參數self裡面
print(self)
print("狗祖宗")
#Dog這個類實例化了一個對象 jinmao
jinmao = Dog()
#對象調用實例化方法info(),執行info()中封裝的代碼 .表示選擇屬性或方法
jinmao.info()
#列印對象,則預設列印對象在記憶體中的地址,結果等同於info中的print(self)
print(jinmao)
#id(taidamier)則時記憶體地址的十進位形式表示
print(id(jinmao))
-----------------------------------------------------------
<__main__.Dog object at 0x00000190A9DC67F0>
狗祖宗
<__main__.Dog object at 0x00000190A9DC67F0>
1720836712432
屬性和變數
屬性和變數的區別
- 屬性:指某個對象的具體特性
- 變數:指可以更改的量
屬性和變數的判斷依據
- 根據宿主判斷:變數無宿主,屬性有宿主
- 根據宿主的不同又分為對象屬性以及類屬性
對象屬性獲取
- 對象既然有實例方法,也可以有自己的屬性
- 在方法內通過self獲取對象屬性
#對象屬性獲取
class Dog(): #定義一個狗類
def move(self): #移動實例方法
print("moving...")
def attack(self): #咬人實例方法
print("咬人")
#實例化一個狗對象 jinmao
jinmao = Dog()
#給對象添加屬性,以及對應的屬性值
jinmao.name = "xiao"
jinmao.hp = 200
jinmao.atk = 40
jinmao.armor = 100
#通過.成員選擇運算符,獲取對象的屬性值
print("%s 的生命值為:%d" %(jinmao.name,jinmao.hp))
print("%s 的攻擊力為:%d" %(jinmao.name,jinmao.atk))
print("%s 的護甲值為:%d" %(jinmao.name,jinmao.armor))
#通過.成員選擇運算符,獲取對象的實例方法
jinmao.move()
jinmao.attack()
-----------------------------------------------------------
xiao 的生命值為:200
xiao 的攻擊力為:40
xiao 的護甲值為:100
moving...
咬人
關於self
- self就是實例化對象本身
#關於self
class A:
def f(self,data):
print(self.name)
print(data)
o = A()
print(A.f)
print(o.f)
-----------------------------------------------------------
<function A.f at 0x000002725D28ADC0>
<bound method A.f of <__main__.A object at 0x000002725D2467F0>>
- 其中A.f對應的時function 即為一個普通的函數
- o.f為bound method 即在函數上綁定了一個對象 —— o
- 結論:o.f 是返回了一個method object ,而當去調用這個object時,他會記住被創建時綁定的對象,即返回該對象,預設參數為self
魔法方法
魔法方法__init__()
__init__方法可以在創建對象時就擁有一些屬性,__init__通常用來做屬性初始化 或 賦值 操作
- 如果類沒有寫__init__方法,python會自動創建,但不會執行任何操作
- 所以一個類里無論自己是否編寫__init__方法 都一定有__init__方法
案例一
#init方法
class Dog():
#方法,用來做變數初始化 或 賦值 操作,在類實例化對象的時候,會被自動調用
def __init__(self,name,hp) -> None:
#__init__方法也可以帶參數
self.name = name
self.hp = hp
print(self.name,self.hp)
#實例化一個對象,並自動調用__init__方法
xiaohuang = Dog("小黃",200)
---------------------------------------------------------
class Dog():
def f(self,name,hp):
self.name = name
self.hp = hp
print(self.name,self.hp)
xiaohuang = Dog()
xiaohuang.f("小黃",200)
案例二
#init方法二
class Dog():
def __init__(self,name,skill,hp) -> None:
self.name = name
self.skill = skill
self.hp = hp
def move(self):
print("%s 正在前往事發地點..." % self.name)
def attack(self):
print("%s 咬人 %s..."%(self.name,self.skill))
def info(self):
print("%s 的生命值:%d"%(self.name,self.hp))
#實例化對象時,參數會傳遞到對象的__init__()方法中
jinmao = Dog("金毛","連環咬",200)
hashiqi = Dog("哈士奇","不鬆口",300)
#直接輸出對象即為地址
print(jinmao)
print(hashiqi)
#不同對象的屬性值的單獨保存
print(id(jinmao.name))
print(id(hashiqi.name))
#同一個類的不同對象,實例方法共用
print(id(jinmao.attack))
print(id(hashiqi.attack))
-----------------------------------------------------------
<__main__.Dog object at 0x000001A3209367F0>
<__main__.Dog object at 0x000001A32089F250>
1800138028976
1800138029168
1800131850880
1800131850880
總結
- 在類內部獲取 屬性 和 實例方法,通過self獲取
- 在類外部獲取 屬性 和 實例方法,通過對象名獲取
- 如果有一個類有多個對象,每個對象的屬性時各自保存的,都有各自獨立的地址
- 實例方法時所有對象共用的,只占用一份記憶體空間
- 類會通過self來判斷是哪個對象,調用了實例方法
魔法方法__str__()
該方法用來顯示信息,通過一個字元串來描述實例對象,該方法需要return一個數據,並且只有self一個參數,在類的外部時用print(對象)列印這個數據(面向用戶)
#str方法
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "此人姓名為%s,此人的年齡為%s"%(self.name,self.age)
p1 = Person("李四",18)
P2 = Person("王五",19)
print(p1)
print(P2)
-------------------------------------------------------------
此人姓名為李四,此人的年齡為18
此人姓名為王五,此人的年齡為19
觸發方式:
1、直接通過print函數去列印
2、通過出發str函數進行轉換
魔法方法__repr__()
通過一個字元串描述實例對象的信息(面向開發人員)
#repr方法
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "此人姓名為%s,此人的年齡為%s"%(self.name,self.age)
p1 = Person("李四",18)
P2 = Person("王五",19)
print(repr(p1))
print(P2)
-------------------------------------------------------------
<__main__.Person object at 0x000001E7D9FD67F0>
此人姓名為王五,此人的年齡為19
#修改repr值
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "此人姓名為%s,此人的年齡為%s"%(self.name,self.age)
def __repr__(self): #更改repr參數值
return "self"
p1 = Person("李四",18)
P2 = Person("王五",19)
print(repr(p1))
print(repr(P2))
print(P2)
-------------------------------------------------------------
self
self
此人姓名為王五,此人的年齡為19
repr與str
在輸出值時當存在str方法便會優先輸出str,repr可以面向開發者,同樣repr方法也可以作為一種方法去輸出str
#repr與str
import datetime
t = datetime.datetime.now()
print(t) #此處輸出的為datetime庫中的類對應的str字元串
print(repr(t)) #同時輸出repr進行對比
-------------------------------------------------------------
2022-07-15 23:53:55.418332 #此為對應字元串輸出值
datetime.datetime(2022, 7, 15, 23, 53, 55, 418332) #此為repr值
#通過eval函數輸出repr
import datetime
t = datetime.datetime.now()
print(t) #此處輸出的為datetime庫中的類對應的str字元串
tmp = repr(t)
result = eval(tmp) #使用eval函數執行輸出repr值的t
print(result)
-------------------------------------------------------------
2022-07-16 00:00:31.144619
2022-07-16 00:00:31.144619
魔法方法__del__()
創建對象後,python解釋器預設調用__init__()方法
當刪除一個對象時,python解釋器也會預設調用一個方法,這個方法叫__del__()
#del方法
class Dog():
#創建對象後__init__方法會自動被調用
def __init__(self, name):
print("__init__方法被調用",name+"出生了")
self.name = name
#當對象執行完畢被刪除時,__del__方法會自動被調用
def __del__(self):
print("__del__方法被調用%s死了"%(self.name))
jinmao = Dog("金毛")
---------------------------------------------------------
__init__方法被調用 金毛出生了
__del__方法被調用金毛死了
繼承
- 子類可以重寫父類的屬性和方法後,依然可以調用父類的屬性和方法
- 使用super方法調用父類
- 多層繼承關係同樣可以實現
- 裝飾器
class Dog(): #創建父類Dog
def __init__(self) -> None:
self.name = "dog dad"
def skill_dad1(self):
print("attack people")
class Dog2(): #創建父類Dog2
def __init__(self) -> None:
self.name = "dog mom"
def skill_mom1(self):
print("attack dog")
def skill_mom2(self):
print("搖尾巴")
class Son(Dog,Dog2):
#創建子類Son並繼承父類Dog和Dog2,繼承時優先繼承第一個父類Dog
def __init__(self) -> None:
self.name = "dog son"
def skill(self):
print("lick people")
def dad_skill(self):
#通過super方法進行調用父類所定義的函數與方法
super().__init__()
super().skill_dad1()
def mom_skill(self):
super().__init__()
super().skill_mom1()
super().skill_mom2()
jinmao = Son()
jinmao.dad_skill()
jinmao.mom_skill()
--------------------------------------------------------------
attack people
attack dog
搖尾巴
多態
- 不同的子對象調用相同的父類放啊,產生不同的結果(繼承+重寫)
- 一個父類可以擁有多個子類繼承
#多態
class Dog():
def __init__(self) -> None:
self.name = "dog mom"
def skill(self):
print("attack dog")
#子類/派生類
class Son1(Dog):
def skill(self):
print("attack man")
class Son2(Dog):
def skill(self):
print("attack woman")
class Son3(Dog):
def skill(self):
print("attack child")
#實例化
son1 = Son1().skill()
son2 = Son2().skill()
son3 = Son3().skill()
---------------------------------------------------------
attack man
attack woman
attack child