python面向对象基础-01
面向?qū)ο?#xff08;OOP)基本概念
前言
話說三國(guó)時(shí)期曹軍于官渡大敗袁紹,酒席之間,曹操詩(shī)興大發(fā),吟道:喝酒唱歌,人生真爽! 眾將直呼:"丞相好詩(shī)",于是命印刷工匠刻板印刷以流傳天下;待工匠刻板完成,交與曹操一看,曹操感覺不妥,說道:"喝酒唱歌,此話太俗,應(yīng)改為'對(duì)酒當(dāng)歌'較好",于是名工匠重新刻板,當(dāng)時(shí)還沒有出現(xiàn)活字印刷術(shù),如果樣板要改,只能重新刻板,工匠眼看連夜刻版之工,徹底白費(fèi),心中叫苦不迭。可也只得照辦。版樣再次出來請(qǐng)曹操過目,曹操細(xì)細(xì)一品,覺得還是不好,說”人生真爽太過直接,應(yīng)該改問語才夠意境,因此應(yīng)改為‘對(duì)酒當(dāng)歌,人生幾何?’“,于是....在活字印刷術(shù)還沒出現(xiàn)之前,如果版樣有改動(dòng),只能重新雕刻。而且在印刷完成后,這個(gè)樣板就失去了它的價(jià)值,如果需要其他樣板只能重新雕刻。而活字印刷術(shù)的出現(xiàn)就大大改善了印刷技術(shù)。如上例”喝酒唱歌,人生真爽“,如果用活字印刷,只需要改四個(gè)字就可,其余工作都未白做。豈不快哉!!活字印刷也反應(yīng)了OOP。當(dāng)要改動(dòng)時(shí),只需要修改部分,此為 可維護(hù);當(dāng)這些字用完后,并非就完全沒有價(jià)值了,它完全可以在后來的印刷中重復(fù)使用,此乃 可復(fù)用;此詩(shī)若要加字,只需另刻字加入即可,這就是 可擴(kuò)展;字的排列可以橫排,也可以豎排,此是 靈活性好。 曹操吟詩(shī)工匠刻錄的故事(轉(zhuǎn)載) # 上述案列反應(yīng)了面向?qū)ο蟮膬?yōu)點(diǎn),即可維護(hù)性高,擴(kuò)展性強(qiáng),復(fù)用性高! # 這些特點(diǎn)非常適用于用戶需求變化頻繁的互聯(lián)網(wǎng)應(yīng)用程序,這是學(xué)習(xí)面向?qū)ο蟮闹匾?/span> # 但是面向?qū)ο笤O(shè)計(jì)的程序需涉及類與對(duì)象,相應(yīng)的復(fù)雜度會(huì)提高! # # 并非所有程序都需要較高的擴(kuò)展性,例如系統(tǒng)內(nèi)核,一旦編寫完成,基本不會(huì)再修改,使用面向過程來設(shè)計(jì)則更適用 小結(jié)面向?qū)ο?/h2>
面向?qū)ο?#xff1a;?# 是一種編程思想,是前輩們總結(jié)的編程經(jīng)驗(yàn),指導(dǎo)程序員如何編寫出更好的程序?
核心:?# 對(duì)象?
程序就是一系列對(duì)象的集合,程序員負(fù)責(zé)調(diào)度控制這些對(duì)象來交互著完成任務(wù) 在面向?qū)ο笾谐绦騿T的角度發(fā)生了改變,從具體的操作者變成了指揮者。
強(qiáng)調(diào):對(duì)象不是憑空產(chǎn)生的,需要我們自己設(shè)計(jì)
面向?qū)ο蟮膬?yōu)缺點(diǎn)
''' 優(yōu)點(diǎn):1.可擴(kuò)展性高2.靈活性高3.重用性高缺點(diǎn):1.程序的復(fù)雜度提高了2.無法準(zhǔn)確預(yù)知結(jié)果 '''使用場(chǎng)景:?# 對(duì)擴(kuò)展性要求較高的程序,通常是直接面向用戶的,例如qq 微信?
注意點(diǎn):?# 不是所有的程序都要采用面向?qū)ο?#xff0c;要根據(jù)實(shí)際需求來選擇?
面向?qū)ο蟮膬纱蠛诵?#xff1a;?# 類與對(duì)象?
類
'''類即類型、類別,是一種 抽象概念是一系列具備相同特征和相同行為的對(duì)象的集合 '''對(duì)象
'''對(duì)象就是具體存在的某個(gè)事物,具備自己的特征和行為對(duì)象就是特征和技能的結(jié)合體 '''類和對(duì)象的關(guān)系
'''類包含一系列對(duì)象對(duì)象屬于某個(gè)類在現(xiàn)實(shí)中先有對(duì)象再有類,程序中先有類再有對(duì)象我們必須先告訴計(jì)算機(jī)這類的對(duì)象有什么特征有什么行為 '''結(jié)論:?# 在面向?qū)ο缶幊虝r(shí),第一步需要考慮需要什么樣的對(duì)象,對(duì)象具備什么樣的特征和行為,從而根據(jù)這些信息總結(jié)出需要的類?
用面向?qū)ο笏枷刖幊?/h1> 類的定義語法及類名書寫規(guī)范
class 類的名稱:# 類中的內(nèi)容,描述屬性和技能# 描述屬性用變量# 描述行為用函數(shù)'''類名書寫規(guī)范:1.見名知意2.名稱是大駝峰式(駝峰就是單詞首字母大寫,大駝峰就是第一個(gè)字母大寫,小駝峰是第一個(gè)字母小寫)3.其他規(guī)范與變量大致相同
''' 屬性
'''
屬性可以寫在類中
類中的屬性,是對(duì)象公共的也可以寫在對(duì)象中
對(duì)象中的屬性,每個(gè)對(duì)象獨(dú)特的(不一樣的)如果類和對(duì)象中存在同樣的屬性,先訪問對(duì)象,如果沒有再訪問類
''' 屬性的增刪改查
'''
增加屬性對(duì)象變量名稱.屬性名稱 = 屬性值egon.male = 'male'
刪除屬性del 對(duì)象的變量名稱.屬性名稱del egon.male
修改屬性 對(duì)象.屬性 = 新的值
查看所有屬性,訪問的是對(duì)象的所有屬性對(duì)象.__dict__ --> dict 可以訪問調(diào)用者自身的名稱空間訪問他的類對(duì)象.__class__ 返回類
''' class Student:'''這是Student類的注釋'''def __init__(self, name):self.name = nameclass TeachOfOldBoy:company = 'oldboy'def __init__(self, name):self.name = name# ---------- 對(duì)象新增、修改、查看、刪除屬性 -------------
xuzhaolong = Student('xzl')
print(xuzhaolong.name) # 對(duì)象.屬性 --> 訪問對(duì)象的屬性
# xzl
# print(xuzhaolong.age) # 訪問不存在的屬性會(huì)報(bào)錯(cuò)'Student' object has no attribute 'age'
xuzhaolong.age = 18 # 對(duì)象.屬性 = 值 --> 為對(duì)象添加新屬性
print(xuzhaolong.age)
# 18
xuzhaolong.age = 28 # 對(duì)象.屬性 = 新值 --> 修改屬性的值(如果該對(duì)象已有此屬性)
print(xuzhaolong.age)
# 28
del xuzhaolong.age # 刪除對(duì)象的屬性
# print(xuzhaolong.age) # 會(huì)報(bào)錯(cuò),屬性已被刪除,類中(屬性的查找順序:對(duì)象-->父類-->...如果還有父類,其他父類...-->Object)沒有這個(gè)屬性,AttributeError: 'Student' object has no attribute 'age'print(TeachOfOldBoy.__dict__) # __dict__查看調(diào)用者的名稱空間里的名字
# {'__module__': '__main__', 'company': 'oldboy', '__init__': <function TeachOfOldBoy.__init__ at 0x0000026D1AC8A9D8>, '__dict__': <attribute '__dict__' of 'TeachOfOldBoy' objects>, '__weakref__': <attribute '__weakref__' of 'TeachOfOldBoy' objects>, '__doc__': None}
print(xuzhaolong.__dict__)
# {'name': 'xzl', 'age': 28}# ---------- __class__ 查看調(diào)用者所屬類型(python里類也是一種數(shù)據(jù)類型) -------------
print(TeachOfOldBoy.__class__) # __class__ 查看調(diào)用者所屬類
# <class 'type'>
print(xuzhaolong.__class__)
# <class '__main__.Student'># ---------- __doc__ 查看調(diào)用者的注釋 -------------
print(TeachOfOldBoy.__doc__) # __doc__ 查看調(diào)用者的注釋
# None
print(Student.__doc__) # __doc__ 查看調(diào)用者所屬類的注釋
#
# 這是Student類的注釋
#
print(xuzhaolong.__doc__) # __doc__ 查看調(diào)用者所屬類的注釋
#
# 這是Student類的注釋
#
# ------------ 類中的屬性與對(duì)象 -----------------
egon = TeachOfOldBoy('egon')
print(egon.company)
# oldboy
egon.company = 'OldBoy'
print(egon.company) # 修改對(duì)象的繼承的屬性不影響類中的屬性
# OldBoy
print(TeachOfOldBoy.company)
# oldboy 代碼體現(xiàn)
屬性的查找順序:?# 屬性的查找順序:先找自己的,再找類的,再父類。。。。一直往上找到object,再?zèng)]有就報(bào)錯(cuò)?
對(duì)象初始化__inint__
''' __init__方法特點(diǎn)1.當(dāng)實(shí)例化對(duì)象時(shí),會(huì)自動(dòng)執(zhí)行__init__方法2.會(huì)自動(dòng)將對(duì)象作為第一個(gè)參數(shù)傳入,對(duì)象參數(shù)名稱為self,self這個(gè)名字可以改,但不建議(一眼就知道是對(duì)象本身了)功能用戶給對(duì)象賦初始值 ''' # 初始化,不僅僅只是賦初值,還可以做一些其他操作,來保證對(duì)象的正常生成 '''之前十個(gè)老師,每個(gè)老師都要輸姓名年齡等,而屬性的值又不一樣,就不能直接定義成類的屬性每定義一個(gè)對(duì)象都要寫一次,很麻煩那么我們可以使用函數(shù)來簡(jiǎn)化這個(gè)賦值操作class Cls: # 定義一個(gè)類passdef init(obj, kind, color, age): # 定義一個(gè)方法來簡(jiǎn)化給對(duì)象添加(定制)屬性obj.kind = kind # 即 對(duì)象.屬性 = 值(變量的) --> 像什么? 給對(duì)象添加屬性嘛obj.color = colorobj.age = ageobj1 = Cls() # 實(shí)例化出一個(gè)對(duì)象init(obj1, "泰日天", '棕色', 2) # 通過調(diào)用 init 函數(shù)來給該對(duì)象添加屬性obj2 = Cls()init(obj2, "拆家犬", '黑白', 1)# 這樣子就有了兩個(gè)對(duì)象,且都已經(jīng)有了各自的屬性了'''class Dog:def __init__(self, kind, color, age):# print(locals()) # {'age': 2, 'color': '棕色', 'kind': '泰日天', 'self': <__main__.Dog object at 0x000002985BE586D8>}self.kind = kindself.color = colorself.age = age# __init__ 函數(shù)不允許寫返回值(不能寫,只能返回None,寫return None 沒有意思) 規(guī)定如此'''不過在類里面直接寫這個(gè) init 函數(shù)會(huì)更方便(python內(nèi)部做了一些處理)如上,當(dāng)實(shí)例化對(duì)象時(shí),會(huì)自動(dòng)執(zhí)行這個(gè) __init__ 方法會(huì)自動(dòng)將調(diào)用這個(gè)類實(shí)例化的對(duì)象作為第一個(gè)參數(shù)傳入,對(duì)象參數(shù)名稱為self'''# 那么在實(shí)例化的時(shí)候就可以簡(jiǎn)寫成這樣了,四行變兩行 teidi = Dog("泰日天", '棕色', 2) # print(teidi.__dict__) # {'kind': '泰日天', 'color': '棕色', 'age': 2} erha = Dog("拆家犬", '黑白', 1)''' 其實(shí)上面的寫法還可以有優(yōu)化,那個(gè)__init__ 函數(shù)還可以寫得更簡(jiǎn)潔一點(diǎn)(參數(shù)越多越明顯)def __init__(self, kind, color, age):lcs = locals()lcs.pop('self')self.__dict__.update(lcs)上面寫法中的locals()內(nèi)置函數(shù)在 __init__ 函數(shù)中,可以獲取 __init__ 函數(shù)名稱空間里的那些名字,它是一個(gè)字典# print(locals()) # {'age': 2, 'color': '棕色', 'kind': '泰日天', 'self': <__main__.Dog object at 0x000002985BE586D8>}我們將其賦給一個(gè)中間字典接收,將多余的 self 鍵值對(duì)去掉,就是我們對(duì)象想要的屬性而對(duì)象.__dict__正好也是一個(gè)字典# print(teidi.__dict__) # {'kind': '泰日天', 'color': '棕色', 'age': 2}都是字典?字典的update()方法還記得嗎?將這個(gè)中間字典update()到對(duì)象的.__dict__ 中,即完成了對(duì)象的屬性添加self.__dict__.update(lcs) ''' __init__
備注:關(guān)于python內(nèi)一些 __名字__ 這種屬性是什么情況,可以參考這篇博客哦(都說不重要,但總有我這樣的好奇寶寶嘛)~? Python常用內(nèi)建方法:__init__,__new__,__class__的使用詳解
綁定方法與非綁定方法
對(duì)象的精髓所在就是將數(shù)據(jù)和處理數(shù)據(jù)的函數(shù)整合到一起了,這樣一來,拿到一個(gè)對(duì)象就同時(shí)拿到了需要處理的數(shù)據(jù)以及處理數(shù)據(jù)的函數(shù)
''' ******* 這一塊基礎(chǔ)概念是重點(diǎn) ******* 對(duì)象綁定方法:self --> 默認(rèn)傳入對(duì)象默認(rèn)情況下,類中的方法都是對(duì)象綁定方法當(dāng)使用對(duì)象調(diào)用時(shí)其特殊之處在于調(diào)用該函數(shù)時(shí)會(huì)自動(dòng)傳入對(duì)象本身作為第一個(gè)參數(shù)當(dāng)使用類名來調(diào)用時(shí)就是一個(gè)普通函數(shù),有幾個(gè)參數(shù)就傳幾個(gè)參數(shù)類綁定方法:@classmethodcls(加上@classmethod裝飾后自己將self改為cls(class是關(guān)鍵字)) --> 默認(rèn)傳入類給類的抽象方法,默認(rèn)傳入類作為參數(shù) 特殊之處:不管用類還是對(duì)象調(diào)用,都會(huì)自動(dòng)傳入類本身,作為第一個(gè)參數(shù)何時(shí)綁定給對(duì)象:當(dāng)函數(shù)邏輯需要訪問對(duì)象中的數(shù)據(jù)時(shí)何時(shí)綁定給類:當(dāng)函數(shù)邏輯需要訪問類中的數(shù)據(jù)時(shí) 非綁定方法:@staticmethod裝飾成普通函數(shù),不管誰調(diào)都一樣既不需要訪問類的數(shù)據(jù)也不需要訪問對(duì)象的數(shù)據(jù)定義時(shí)有幾個(gè)參數(shù)調(diào)用時(shí)就需要傳入幾個(gè)參數(shù)''' class Dog:species = 'dog'# 初始化方法 __init__ 也屬于對(duì)象綁定方法def __init__(self, kind, nickname, skill):self.kind = kindself.nickname = nicknameself.skill = skill# 這就屬于一個(gè)對(duì)象綁定方法,默認(rèn)將對(duì)象作為第一個(gè)參數(shù)傳入(調(diào)用的時(shí)候不需要手動(dòng)傳入)def introduce(self):print(f"我是{self.kind},我能{self.skill},人送外號(hào){self.nickname}")# 類綁定方法 @classmethoddef tell_species(cls): # 先寫裝飾器再寫函數(shù),默認(rèn)參數(shù)就是cls了,寫完函數(shù)再裝飾的話,記得把self換成cls,表示參數(shù)是一個(gè)類print(f"我的物種是{cls.species}")# 非綁定方法(既不需要傳入類,也不需要傳入對(duì)象) @staticmethoddef normal_func(arg1, arg2):print(f"參數(shù)一:{arg1} 參數(shù)二:{arg2},這只是一個(gè)普通方法啦~")taidi = Dog('泰迪', '泰日天', '日天') erha = Dog('二哈', '拆家犬', '拆家')# --------綁定對(duì)象方法的調(diào)用 taidi.introduce() erha.introduce() # 我是泰迪,我能日天,人送外號(hào)泰日天 # 我是二哈,我能拆家,人送外號(hào)拆家犬 Dog.introduce(erha) # 類調(diào)用對(duì)象的方法要手動(dòng)把對(duì)象傳入進(jìn)去 # 我是二哈,我能拆家,人送外號(hào)拆家犬# --------類綁定方法調(diào)用 Dog.tell_species() taidi.tell_species() # 可以直接調(diào)用,無需手動(dòng)傳入 class # 我的物種是dog # 我的物種是dog# --------非綁定方法調(diào)用 Dog.normal_func(1, 2) # 非綁定方法,定義時(shí)有幾個(gè)參數(shù),調(diào)用時(shí)就要傳幾個(gè)參數(shù) taidi.normal_func(1, 2) # 非綁定方法,定義時(shí)有幾個(gè)參數(shù),調(diào)用時(shí)就要傳幾個(gè)參數(shù) # 參數(shù)一:1 參數(shù)二:2,這只是一個(gè)普通方法啦~ # 參數(shù)一:1 參數(shù)二:2,這只是一個(gè)普通方法啦~ 對(duì)象綁定方法、類綁定方法、非綁定方法利用pickle模塊將對(duì)象序列化到本地
如單機(jī)游戲的存檔(把對(duì)象的數(shù)據(jù)等信息存儲(chǔ)到文件中,下次啟動(dòng)再讀取回來) --> 游戲擴(kuò)展
import pickleclass Student:def __init__(self, name):self.name = namedef say_hi(self):print("name:", self.name)def save(self):with open(self.name, "wb") as f: # pickle 模塊操作文件必須是b 模式pickle.dump(self, f) # 利用pickle 模塊,將傳入的對(duì)象序列化到了文件中(json模塊不支持對(duì)象這種類型) @staticmethoddef get(name):with open(name, "rb") as f:obj = pickle.load(f) # 利用pickle 模塊,將文件中的對(duì)象反序列化成python中的對(duì)象return obj# 將rose 和 jack兩個(gè)從內(nèi)存中對(duì)象序列化到文件中 stu = Student("rose") stu.save() stu2 = Student("jack") stu2.save()# 將他兩反序列化出來到內(nèi)存中 obj = Student.get("rose") # 調(diào)用類中的方法(類綁定方法)從文件中將對(duì)象加載到內(nèi)存中 print(obj.name) # 使用該對(duì)象獲取屬性值 # rose obj2 = Student.get("jack") print(obj2.name) # jackprint(Student.__name__) # 獲取類名 # Student# 反序列化出來的對(duì)象和序列化的那個(gè)對(duì)象已經(jīng)不是同一個(gè)對(duì)象了 print(id(stu), id(obj)) # 2161209937816 2161209971880 print(stu.name, obj.name) # rose rose print(id(stu2), id(obj2)) # 2161209937872 2161209971824 print(stu2.name, obj2.name) # jack jack obj2.name = 'jack2' print(stu2.name, obj2.name) # jack jack2 將對(duì)象從內(nèi)存中序列化反序列化到文件中英雄大亂斗(隨機(jī))案例
import random import timeclass Hero:def __init__(self, name, health, attack, q_hurt, w_hurt, e_hurt):lcs = locals()lcs.pop('self')self.__dict__.update(lcs)def attack(self, enemy):print(f"-- {self.name} --使用普通攻擊攻擊了-- {enemy.name} --,造成了 {self.attack} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")enemy.health -= self.attackdef Q(self, enemy):print(f"\033[0m-- {self.name} --使用Q技能攻擊了-- {enemy.name} --,造成了 {self.q_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")enemy.health -= self.q_hurtdef W(self, enemy):print(f"\033[32m-- {self.name} --使用W技能攻擊了-- {enemy.name} --,造成了 {self.w_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")enemy.health -= self.w_hurtdef E(self, enemy):print(f"\033[35m-- {self.name} --使用E技能攻擊了-- {enemy.name} --,造成了 {self.e_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")enemy.health -= self.e_hurtdef check_hero(enemy, team):if enemy.health <= 0:print(f"\033[31m** {enemy.name} ** 陣亡。\033[0m")if team == 'blue':blue_team.remove(enemy)elif team == 'red':red_team.remove(enemy)def get_random_skill():return skill_list.get(random.randint(1, 4))def get_random_blue_hero():return blue_team[random.randint(0, len(blue_team) - 1)]def get_random_red_hero():return red_team[random.randint(0, len(red_team) - 1)]blue_team = [Hero('瑞文', 465, 65, 30, 25, 70),Hero('提莫', 300, 35, 50, 40, 60), ]red_team = [Hero('李白', 320, 60, 35, 29, 77),Hero('魯班', 280, 79, 35, 40, 80), ]skill_list = {1: Hero.attack,2: Hero.Q,3: Hero.W,4: Hero.E, }while len(red_team) > 0 and len(blue_team) > 0:skill = get_random_skill()blue = get_random_blue_hero()red = get_random_red_hero()flag = random.randint(0, 1)if flag:skill(blue, red)check_hero(red, 'red')else:skill(red, blue)check_hero(blue, 'blue')time.sleep(0.3)if len(red_team) == 0:print(f"藍(lán)色方獲勝!")print(f"藍(lán)色方所剩英雄狀態(tài)為:")for hero in blue_team:print(f"{hero.name} 剩余生命值 {hero.health}")elif len(blue_team) == 0:print(f"紅色方獲勝!")print(f"紅色方所剩英雄狀態(tài)為:")for hero in red_team:print(f"{hero.name} 剩余生命值 {hero.health}") 無注釋版注釋版
import random import time# 定義一個(gè)英雄類,表示英雄這一類的共同特征 class Hero:def __init__(self, name, health, attack, q_hurt, w_hurt, e_hurt):lcs = locals()lcs.pop('self')self.__dict__.update(lcs)'''********************************** 上述代碼講解 *************************************# 每次調(diào)用類生成對(duì)象的時(shí)候都會(huì)執(zhí)行這里面的代碼,并將對(duì)象作為第一個(gè)參數(shù)self 傳進(jìn)來print(locals())# {'e_hurt': 70, 'w_hurt': 25, 'q_hurt': 30, 'attack': 65, 'health': 465, 'name': '瑞文', 'self': <__main__.Hero object at 0x000002371823B278>}lcs = locals() # 這個(gè)locals()在 __init__ 函數(shù)里 可以獲取 __init__ 函數(shù)名稱空間里的那些名字,他是一個(gè)字典lcs.pop('self') # 發(fā)現(xiàn)上面的 locals() 多了一個(gè) self 是不需要的,那就把它刪掉print(lcs)# {'e_hurt': 70, 'w_hurt': 25, 'q_hurt': 30, 'attack': 65, 'health': 465, 'name': '瑞文'}# 這些內(nèi)容正是初始化對(duì)象時(shí)想做的事(只不過是 對(duì)象.e_hurt = 70 這樣的形式而已)self.__dict__.update(lcs) # 將這些東西放到對(duì)象里,就重復(fù)了n變 self.參數(shù) = 參數(shù) (self.name = name)這樣的動(dòng)作print(self.__dict__)# {'e_hurt': 70, 'w_hurt': 25, 'q_hurt': 30, 'attack': 65, 'health': 465, 'name': '瑞文'}最初始的寫法:self.name = nameself.health = healthself.attack = attackself.q_hurt = q_hurtself.w_hurt = w_hurtself.e_hurt = e_hurt'''def attack(self, enemy):enemy.health -= self.attackprint(f"-- {self.name} --使用普通攻擊攻擊了-- {enemy.name} --,造成了 {self.attack} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")def Q(self, enemy):enemy.health -= self.q_hurtprint(f"\033[0m-- {self.name} --使用Q技能攻擊了-- {enemy.name} --,造成了 {self.q_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")def W(self, enemy):enemy.health -= self.w_hurtprint(f"\033[32m-- {self.name} --使用W技能攻擊了-- {enemy.name} --,造成了 {self.w_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")def E(self, enemy):enemy.health -= self.e_hurtprint(f"\033[35m-- {self.name} --使用E技能攻擊了-- {enemy.name} --,造成了 {self.e_hurt} 點(diǎn)傷害,{enemy.name} 剩余 {enemy.health} 點(diǎn)生命值。\033[0m")def check_hero(enemy, team):if enemy.health <= 0:# \033[31m 這種格式的是打印時(shí)的顏色控制(顏色可參考 https://www.cnblogs.com/easypython/p/9084426.html)print(f"\033[31m** {enemy.name} ** 陣亡。\033[0m")if team == 'blue':blue_team.remove(enemy)elif team == 'red':red_team.remove(enemy)# 隨機(jī)選擇一種攻擊方式 def get_random_skill():# random_index = random.randint(1, 4)# random_skill = skill_list.get(random_index)# return random_skill # 函數(shù)名當(dāng)做返回值返回,拿到可以直接加括號(hào)調(diào)用執(zhí)行函數(shù)return skill_list.get(random.randint(1, 4)) # 上面代碼的簡(jiǎn)便寫法# 隨機(jī)選擇一個(gè)藍(lán)色方英雄 def get_random_blue_hero():# 返回 blue_team 這個(gè)列表的索引為 random.randint(0, len(blue_team) - 1) 返回值的元素(英雄對(duì)象)# return blue_team[random.randint(0, len(blue_team) - 1)] # 下面幾行的簡(jiǎn)便寫法random_idndex = random.randint(0, len(blue_team) - 1)hero = blue_team[random_idndex]return hero# 隨機(jī)選擇一個(gè)紅色方英雄 def get_random_red_hero():return red_team[random.randint(0, len(red_team) - 1)]# 藍(lán)色方英雄陣容 --- 可自定義 --- # 方便隨機(jī)數(shù)取英雄對(duì)象 blue_team = [# 英雄名 生命值 普通攻擊力 Q技能傷害 W技能傷害 E技能傷害# 瑞文 465 65 30 25 70Hero('瑞文', 465, 65, 30, 25, 70),Hero('提莫', 300, 35, 50, 40, 60),Hero('錘石', 600, 15, 20, 0, 32), ]# 紅色方英雄陣容 --- 可自定義 --- # 方便隨機(jī)數(shù)取英雄對(duì)象 red_team = [Hero('李白', 320, 60, 35, 29, 77),Hero('魯班', 280, 79, 35, 40, 80),Hero('盾山', 800, 3, 3, 3, 3), ]# 技能數(shù)字對(duì)應(yīng)表(方便根據(jù)隨機(jī)數(shù)取技能) skill_list = {1: Hero.attack,2: Hero.Q,3: Hero.W,4: Hero.E, }def run():while len(red_team) > 0 and len(blue_team) > 0:# 調(diào)用方法隨機(jī)獲得一個(gè)技能skill = get_random_skill()# 調(diào)用方法隨機(jī)獲得一個(gè)藍(lán)色方英雄blue = get_random_blue_hero()# 調(diào)用方法隨機(jī)獲得一個(gè)紅色方英雄red = get_random_red_hero()# 隨機(jī)選擇一方為攻擊方(那么另一方就是被攻擊方)flag = random.randint(0, 1)if flag:skill(blue, red)check_hero(red, 'red')else:skill(red, blue)check_hero(blue, 'blue')# 暫停0.3秒,可以慢慢看戰(zhàn)斗過程time.sleep(0.3)# 如果有任意一方?jīng)]有英雄了,即游戲結(jié)束if len(red_team) == 0:print(f"藍(lán)色方獲勝!")print(f"藍(lán)色方所剩英雄狀態(tài)為:")for hero in blue_team:print(f"{hero.name} 剩余生命值 {hero.health}")elif len(blue_team) == 0:print(f"紅色方獲勝!")print(f"紅色方所剩英雄狀態(tài)為:")for hero in red_team:print(f"{hero.name} 剩余生命值 {hero.health}")if __name__ == '__main__':run()'''戰(zhàn)斗記錄************************** 省略n多中間戰(zhàn)斗步驟 *********************************-- 錘石 --使用W技能攻擊了-- 盾山 --,造成了 0 點(diǎn)傷害,盾山 剩余 42 點(diǎn)生命值。-- 盾山 --使用E技能攻擊了-- 瑞文 --,造成了 3 點(diǎn)傷害,瑞文 剩余 289 點(diǎn)生命值。-- 瑞文 --使用E技能攻擊了-- 盾山 --,造成了 70 點(diǎn)傷害,盾山 剩余 -28 點(diǎn)生命值。** 盾山 ** 陣亡。藍(lán)色方獲勝!藍(lán)色方所剩英雄狀態(tài)為:瑞文 剩余生命值 289錘石 剩余生命值 235戰(zhàn)斗記錄2************************** 省略n多中間戰(zhàn)斗步驟 *********************************-- 盾山 --使用普通攻擊攻擊了-- 錘石 --,造成了 3 點(diǎn)傷害,錘石 剩余 11 點(diǎn)生命值。-- 錘石 --使用普通攻擊攻擊了-- 盾山 --,造成了 15 點(diǎn)傷害,盾山 剩余 288 點(diǎn)生命值。-- 盾山 --使用E技能攻擊了-- 瑞文 --,造成了 3 點(diǎn)傷害,瑞文 剩余 -1 點(diǎn)生命值。** 瑞文 ** 陣亡。-- 盾山 --使用普通攻擊攻擊了-- 錘石 --,造成了 3 點(diǎn)傷害,錘石 剩余 8 點(diǎn)生命值。-- 盾山 --使用普通攻擊攻擊了-- 錘石 --,造成了 3 點(diǎn)傷害,錘石 剩余 5 點(diǎn)生命值。-- 盾山 --使用W技能攻擊了-- 錘石 --,造成了 3 點(diǎn)傷害,錘石 剩余 2 點(diǎn)生命值。-- 盾山 --使用Q技能攻擊了-- 錘石 --,造成了 3 點(diǎn)傷害,錘石 剩余 -1 點(diǎn)生命值。** 錘石 ** 陣亡。紅色方獲勝!紅色方所剩英雄狀態(tài)為:盾山 剩余生命值 288'''''' 有紅藍(lán)兩方英雄(可自定義個(gè)數(shù))隨機(jī)一方英雄使用隨機(jī)攻擊方式攻擊另一方英雄,任意一方英雄全部陣亡則游戲結(jié)束每個(gè)英雄有 名字、生命值、普通攻擊、Q技能攻擊、W技能攻擊、E技能攻擊以及對(duì)應(yīng)的傷害值當(dāng)生命值為 0 時(shí)陣亡,不再參與戰(zhàn)斗 ''' 注釋版案例后續(xù)完善博客思路
調(diào)用類生成對(duì)象發(fā)生的一些事情(對(duì)比變量、模塊名稱空間生成等)屬性的查找順序(畫圖表示吧)先找自己的,再找父類的,一級(jí)一級(jí)往上找,直到基類object,再?zèng)]有報(bào)錯(cuò)英雄大亂斗案例 序列化、反序列化對(duì)象(保存、讀取對(duì)象)(游戲退出,讀檔) 待完善內(nèi)容(不算是面向?qū)ο蟮闹攸c(diǎn)啦)?
轉(zhuǎn)載于:https://www.cnblogs.com/suwanbin/p/11240814.html
總結(jié)
以上是生活随笔為你收集整理的python面向对象基础-01的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阶梯博弈(Staircase Nim)
- 下一篇: python第三次作业