面向物件基礎、類和物件、繫結方法
一、面向物件程式設計
回顧:面向過程程式設計
是一種之前程式設計師們設計出來的比較好的程式設計方法,也是一種程式設計思想。
核心是過程二字,顧名思義,就是先幹什麼,再幹什麼,完成一個事情具有的所有步驟。
優點:複雜的流程簡單化,程式化,一步一步拆分,降低開發難度。
缺點:擴充套件性差, 不容易維護。
主要使用的場景:對擴充套件性要求不高的,如Linux核心,shell指令碼
何為面向物件?
核心是‘物件’二字。
與面向過程機械式的思維方式形成鮮明對比,面向物件更加註重對現實世界而非流程的模擬,是一種“上帝式”的思維方式。
優點:
1.對於指揮者(程式設計師)來說,不需要再關心具體步驟 2.擴充套件性,一個單獨的個體的特徵或行為發生變化時 不會影響到別人
缺點:
1.程式的複雜度變高,你得需要設計這些物件,注意要避免過度設計得問題 2.程式得執行結果可控性低
二、類和物件
什麼是物件:
在現實生活中實實在在存在的,具備自己的特徵和行為的事物 反過來說 物件就是 特徵和行為(技能)的結合體
什麼是類
一堆具備相同特徵和行為的事物的抽象概念,不實際存在。
conclusion:
先有類還是先有物件: 生活中: 生活中類怎麼來的,是通過物件的特徵和行為抽取而來, 所以是先有物件才有了類
程式設計中: 必須是先有類 才能有物件,因為你必須先告訴程式,你這個物件有什麼樣的特徵和行為
類的作用:用於描述該類的物件具備什麼樣的特徵和行為
補充說明:
站的角度不同,定義出的類是截然不同的;
現實中的類並不完全等於程式中的類,比如現實中的公司類,在程式中有時需要拆分成部門類,業務類等;
有時為了程式設計需求,程式中也可能會定義現實中不存在的類,比如策略類,現實中並不存在,但是在程式中卻是一個很常見的類
三、Python中類和物件的操作
class Student: # 如果每個物件的這個屬性都相同 才應該定義到類中 比如所有人的學校都相同 school = "北京大學"
# 建立物件 # 語法: 在類名後加括號 與呼叫函式寫法相同 # stu = Student()# # 訪問物件的屬性 # print(stu.school) # print(Student.school)
# 修改屬性的值 # stu.school = "清華大學" # print(stu.school) # # # 增加屬性 # stu.room_num = "1008" # print(stu.room_num) # # # 刪除屬性 # del stu.room_num # print(stu.room_num)
# 物件 與類的名稱空間是獨立的 # stu.school = "深圳大學" # 為物件的屬性賦予新的值 # print(Student.school) # 類中的屬性不會變化 # stu.room_num = "1008" # 為物件增加屬性 # # print(Student.room_num) #類中也不會出現新的屬性 # print(stu.__dict__) # print(Student.__dict__)
物件的屬性查詢順序:物件自己的名稱空間 -> 類的名稱空間
四、__init__方法詳解
該方法是在物件產生之後才會執行,只用來為物件進行初始化操作,可以有任意程式碼,但一定不能有返回值。
__init__稱之為初始化函式 它會在建立物件的時候自動執行建立物件時1.建立一個空物件2.執行__init__函式 並且自動傳入了這個物件
該函式的作用,就是為物件的屬性賦初始值
def __init__(self,name,color,age,gender): print("狗__init__執行了") print(self) self.name = name self.age = age self.color = color self.gender = gender
# 在建立物件時,傳入引數 dog1 = Dog("大黃","黃色",2,"female") dog2 = Dog("二哈","白色",2,"female") print(dog1.__dict__) print(dog2.__dict__)
注意:
1. 使用場景 需要為每個物件定製不同的屬性值2.__init__在建立物件後自動執行3.第一個self引數 指的是這個物件本身 不需要手動傳值
五、繫結方法
class Person: country = "China" def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def sleep(self): print("sleeping")def eat(self): print("eating")
# p1 = Person("矮根",68,"female") # p2 = Person("成偉",18,"female") # 類呼叫類中函式 與 物件呼叫的區別 # p1.sleep() # p2.sleep() # print(Person.sleep) # print(p1.sleep) # 類呼叫 # Person.sleep(10) # 物件呼叫 # p1.sleep()
類呼叫與物件呼叫的區別對於類而言 sleep就是一個普通函式對物件而言 sleep是一個繫結方法
繫結方法是什麼?是物件與類中的某個函式的繫結關係 就像生活中 我們都會吃飯 我吃飯你不會飽那麼吃飯就是我自己的繫結方法
為什麼要把函式進行繫結? 因為物件的行為 通常都需要訪問這個物件的資料 或是修改這個物件的資料 如果沒有物件 直接呼叫函式是沒有意義的 在函式中訪問不到物件的資料 所以將物件和函式進行繫結
特殊之處在使用繫結方法時 不需要關心self引數 會自動將這個物件本身傳進來 物件呼叫繫結方法時 最後執行的還是類中的那個函式
練習題:
模擬一個王者榮耀對砍遊戲,兩個英雄可以對砍 如果血量小於等於0 就GG,考慮所需的物件和英雄的物件。
class Hero: def __init__(self,hero_type,name,blood,q,w,e): self.hero_type = hero_type self.blood = blood self.name = name self.q = q self.w = w self.e = e def Q(self,enemy):# 跳起來給你一刀 print('%s 對 %s 釋放了Q技能 造成%s點傷害,對方剩餘血量%s' %(self.name,enemy.name,self.q,enemy.blood-self.q)) enemy.blood -=self.q if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) def W(self,enemy):# 給你一腳 print('%s 對 %s 釋放了W技能 造成%s點傷害,對方剩餘血量%s' %(self.name,enemy.name,self.w,enemy.blood-self.w)) enemy.blood -=self.w if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) def E(self,enemy):# 大寶劍 print('%s 對 %s 釋放了Q技能 造成%s點傷害,對方剩餘血量%s' %(self.name,enemy.name,self.e,enemy.blood-self.e)) enemy.blood -= self.e if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) # 定義英雄的物件 yashe = Hero('戰士','亞瑟',200,50,30,100) #q,w,e 50,30,100 daji = Hero('法師','妲己',180,10,30,180) #q,w,e 10,30,180 yashe.E(daji) daji.W(yashe) yashe.W(daji) daji.Q(yashe) yashe.Q(daji)
輸出:
亞瑟 對 妲己 釋放了Q技能 造成100點傷害,對方剩餘血量80 妲己 對 亞瑟 釋放了W技能 造成30點傷害,對方剩餘血量170 亞瑟 對 妲己 釋放了W技能 造成30點傷害,對方剩餘血量50 妲己 對 亞瑟 釋放了Q技能 造成10點傷害,對方剩餘血量160 亞瑟 對 妲己 釋放了Q技能 造成50點傷害,對方剩餘血量0 Hero 妲己 is GG