一、人狗大戰 1、需求 用代碼模擬人、狗打架的小游戲 人和狗種類不同,因此雙方的屬性各不相同 推導一: 人和狗各有不同屬性 使用字典方式儲存屬性較為方便,並可儲存多種屬性 # 1、在字典內儲存‘人’屬性 person = { 'name': '阿拉蕾', 'age': 18, 'gender': ' ...
一、人狗大戰
1、需求
-
用代碼模擬人、狗打架的小游戲
-
人和狗種類不同,因此雙方的屬性各不相同
推導一:
- 人和狗各有不同屬性
- 使用字典方式儲存屬性較為方便,並可儲存多種屬性
# 1、在字典內儲存‘人’屬性
person = {
'name': '阿拉蕾',
'age': 18,
'gender': '女',
'p_type': '戰士',
'attack_val': 8000,
'life_val': 99999999
}
# 2、在字典內儲存‘狗’特有屬性
dog1 = {
'name': '小黑',
'd_type': '泰迪',
'attack_val': 100,
'life_val': 8000
}
推導二:
- 按照上述方法,如果想要定義多個‘人’和‘狗’就需要反覆設置多個字典,這樣非常麻煩且費時
- 這時可推導出,想要快速、便捷的定義多個‘人’和‘狗’,那麼我們可以把字典內的數據封裝在函數內,利用傳參的方式,這樣可以較為方便的生成多個‘人’和‘狗’,只需要使用不同變數名調用函數時傳不同的參數即可
# 1、封裝‘人’屬性函數
def create_person(name, age, gender, p_type, attack_val, life_val):
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val
}
return person_dict
# 2、封裝‘狗’屬性的函數
def create_dog(name, d_type, attack_val, life_val):
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val
}
return dog_dict
# 3、生成多個‘人’和‘狗’
p1 = create_person('阿拉蕾', 18, '男', '戰士', 8000, 99999999)
p2 = create_person('小朵朵', 28, '女', '法師', 100, 800)
d1 = create_dog('小黑', '泰迪', 100, 8000)
d2 = create_dog('小白', '鬥牛', 100, 800000)
推導三:
- ‘人’和‘狗’就類似於各自不同種類的對象
- 說到這裡,我們就應該明白,‘人’和‘狗’因為種類不同,所以雙方的屬性也各不相同,也就是說不同的對象,屬性(數據)各不相同
- 當多個對象的屬性生成後,我們就要開始定義彼此打架的動作(功能)
- 人打狗的動作
- 狗咬人的動作
# 1、人打狗的動作
def person_attack(person_dict, dog_dict):
print(f"{person_dict.get('name')}踢向{dog_dict.get('name')}")
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f"人踢了狗一腳 狗掉血:{person_dict.get('attack_val')} 狗剩餘血量:{dog_dict.get('life_val')}")
# 2、狗打人的動作
def dog_attack(dog_dict, person_dict):
print(f"{dog_dict.get('name')}向{person_dict.get('name')}咬去")
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩餘血量:{person_dict.get('life_val')}")
# 3、調用雙方各自的函數,即可模擬出雙方打架的動作
person_attack(p1, d1) # 人打狗
dog_attack(d2, p2) # 狗咬人
-------------------------------------------------------
阿拉蕾踢向小黑
人踢了狗一腳 狗掉血:8000 狗剩餘血量:0
小白向小朵朵咬去
狗咬了人一口 人掉血:100 人剩餘血量:700
2、核心思路
- ‘人’和‘狗’就是不同的對象
- 通過將不同的屬性封裝在不同的函數內,就可以通過相同的函數快速生成不同屬性的對象
- ‘人’和‘狗’打架的方式就是對象的功能
- 人的打架方式是踢,狗的打架方式是咬,也就是說不同的類有著不同的功能,而相同的類就可以有著彼此相同的功能
需求:
- 以上我們完成了不同種類的打架方式,但是在python中,如果沒有特別的限制,我們就可以把人攻擊的數據傳在狗攻擊函數內,這樣就會產生混亂,要如何實現下列需求
- ‘人’只能調用人的攻擊方式
- ‘狗’只能調用狗的攻擊方式
推導一:
"""推導步驟4:如何實現只有人只能調用的人的攻擊動作 狗只能調用狗的攻擊動作>>>:數據與功能的綁定"""
def get_person(name, age, gender, p_type, attack_val, life_val):
# 產生人的函數(功能)
def person_attack(person_dict, dog_dict):
print(f"{person_dict.get('name')}踢向{dog_dict.get('name')}")
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f"人踢了狗一腳 狗掉血:{person_dict.get('attack_val')} 狗剩餘血量:{dog_dict.get('life_val')}")
# 表示人的信息(數據)
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val,
'person_attack': person_attack
}
return person_dict
def get_dog(name, d_type, attack_val, life_val):
def dog_attack(dog_dict, person_dict):
print(f"{dog_dict.get('name')}向{person_dict.get('name')}咬去")
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩餘血量:{person_dict.get('life_val')}")
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val,
'dog_attack': dog_attack
}
return dog_dict
person1 = get_person('jason', 18, 'male', '猛男', 8000, 99999999)
dog1 = get_dog('小黑', '惡霸', 800, 900000)
person1.get('person_attack')(person1, dog1)
結論:
- 通過上列代碼,我們將人的專屬攻擊方式,封裝在了人的類別內,實現了人專屬的屬性和功能,當人在調用自身類別,並傳入符合條件的參數時,就可以生成一個人(對象)特有的屬性(數據)和攻擊方式(功能)
- 同上,我們也可將狗的數據和攻擊方式封裝在狗特有的函數內,當我們生成多條狗的時候,每條狗也就有了,狗(對象)特有的屬性(數據)和攻擊方式(功能)
人狗大戰推導就是面對對象的核心思想:數據與功能的綁定!!
二、編程思想
引言:
-
面向對象是一種編程思想,用這種思想為指導設計的程式,把數據和對數據的操作封裝在一起組成類,通過類來創建對象,通過對象之間的交互來實現程式的功能。
-
面向對象編程是一種編程方式,此編程方式的落地需要使用 “類” 和 “對象” 來實現,所以,面向對象編程其實就是對 “類” 和 “對象” 的使用
1、面向過程編程
- 面向過程即流程
- 在以上所學習的編程中,我們都是在按照固定的流程解決問題,制定一個結果,在奔向結果的過程中編寫代碼,以達到我們所需要的結果
- 需要例舉出每一步流程 隨著流程的深入 結果慢慢浮現
2、面向對象編程
- 對象即容器,數據與功能的結合體 (python中一切皆對象)
- 類似於開放式游戲,制定出游戲人物的(對象)
- 該人物未來會如何發展,全看用戶如何控制,和我們程式員沒有關係
- 類似於王者榮耀,玩家控制英雄走向
- 類似於王者榮耀,玩家控制英雄走向
上述兩種編程思想沒有優劣之分 需要結合實際需求而定
如果需求是註冊 登錄 人臉識別肯定面向過程更合適
如果需求是游戲人物肯定是面向對象更合適
實際編程兩種思想是彼此交融的 只不過占比不同
三、面向對象
1、類與對象
對象:
- 數據與功能的結合體
- 是由類創建出來的一個具體存在,可以直接使用;由哪一個類創建出來的對象,該對象就具有在那一個類中定義的屬性和方法
類:
- 多個對象相同數據和功能的結合體
- 是對一群具有相同特征或者行為的事物的一個統稱,不能直接使用;特征被稱為屬性;行為被稱為方法。
2、類與對象的創建
現實中一般是先有對象再有類
程式中如果想要產生對象 必須要先定義出類
1.語法結構
class 類名:
'''代碼註釋'''
對象公共的數據
對象公共的功能
1.class是定義類的關鍵字
2.類名幾乎和變數名一致,使用的時候推薦類名的首字母大寫
3.數據:
變數名與數據值的綁定
功能:
功能(方法)其實就是具有一定功能的函數
2.定義與調用
需求:
- 清華大學選課系統
'''
類在定義階段就會執行類函數體代碼
但類的函數體代碼外界無法直接調用
'''
1、定義類
class Student:
# 對象公共的數據
school_name = '清華大學'
# 對象公共的功能
def choice_course(self):
print('學生選課功能')
查看類的名稱空間:
- 在面向對象中,類和對象訪問數據或者功能,可以統一採用句點符
print(Student.__dict__)
# {'__module__': '__main__', 'school_name': '清華大學', 'choice_course': <function Student.choice_course at 0x0000018FCCCD5670>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
print(Student.__dict__.get('school_name'))
# 清華大學
print(Student.__dict__ .get('choice_course'))
# <function Student.choice_course at 0x000001417B975670>
類的調用:
- 類加括弧就會產生對象,並且每調用一次就會產生一個全新的對象
- 變數名obj接收類名加括弧之後的返回值(結果)
1、調用對象
obj1 = Student()
# <__main__.Student object at 0x000001992C2759D0>
obj2 = Student()
# <__main__.Student object at 0x000001992C278E50>
obj3 = Student()
# <__main__.Student object at 0x000001992C278E20>
'''
三個變數名的地址各不相同,產生三個對象
'''
2、查看對象內部數據
print(obj1.__dict__,
obj2.__dict__,
obj3.__dict__)
# {} {} {}
'''
三個對象各自內部都為空
'''
3、調用對象共同數據
print(obj1.school_name)
# 清華大學
print(obj2.school_name)
# 清華大學
print(obj3.school_name)
# 清華大學
'''
同一類產生的對象,都可使用類內部公用數據值
'''
數據和功能可稱統稱為屬性:
數據>>>屬性名
功能>>>方法
3、對象獨有數據
在上述使用類產生對象時,我們可以看出產生的對象並沒有自己特有的數據,針對如何給對象手動添加獨有數據,python提供了多種方式,其中前4種方式主要為推導第五種方式而來,我們只需簡單瞭解即可,在日後我們重點使用的是第五種方式
第一種:
- 通過__ dict __ 加中括弧的方式
obj1.__dict__['name'] = 'jason'
obj1.__dict__['age'] = 18
obj1.__dict__['hobby'] = 'study'
第二種:
- 將對象獨有的數據提前封裝成函數,在後續添加的時候,通過傳參的方式進行添加
def init(obj,name,age,hobby)
obj.__dict__['name'] = name
obj.__dict__['age'] = age
obj.__dict__['hobby'] = hobby
init(ojb1.'kangkang', 18, 'read')
init(ojb2, 'zhangzhang', 28, 'ball')
第三種:
- 將封裝數據的函數放在類的內部,只有相同類的對象才有資格使用
class Student:
# 對象公用的數據
school_name = '清華大學'
# 專門給學生添加獨有數據的功能
def init(obj, name, age, hobby):
obj.__dict__['name'] = name
obj.__dict__['age'] = age
obj.__dict__['hobby'] = hobby
# 對象公共的功能
def choice_course(self):
print('學生選課功能')
stu1 = Student()
Student.init(stu1, 'kangkang', 18 , 'read')
Student.init(stu2, 'zhangzhang', 28 , 'ball')
第四種:
- 將封裝獨有功能的函數名替換成__ init __ 這種方式,在我們給對象添加獨有功能時,可自動觸發
class Student:
# 對象公用的數據
school_name = '清華大學'
# 專門給學生添加獨有數據的功能
def __init__(obj, name, age, hobby):
obj.__dict__['name'] = name
obj.__dict__['age'] = age
obj.__dict__['hobby'] = hobby
# 對象公共的功能
def choice_course(self):
print('學生選課功能')
stu1 = Student('kangkang', 18, 'read')
Stu2 = Student('zhangzhang', 28, 'ball')
第五種:
-
封裝獨有數據的函數體的第一個參數位置修改為self
-
在使用類產生對象時直接在類的括弧內填入獨有數據
-
這種方式是我們日後使用類產生獨有數據對象的主要方式
class Student:
# 對象公用的數據
school_name = '清華大學'
# 專門給學生添加獨有數據的功能
def __init__(self, name, age, hobby):
self.__dict__['name'] = name
self.__dict__['age'] = age
self.__dict__['hobby'] = hobby
# 對象公共的功能
def choice_course(self):
print('學生選課功能')
stu1 = Student('kangkang', 18, 'read')
stu1 = Student('zhangzhang', 18, 'ball')
4、對象獨有功能
上述學習瞭如何給相同類對象添加獨有數據的方式,下麵我們要學習如何給對象添加獨有功能
思考:
- 1、直接將功能函數體代碼定義在全局名稱空間種,那麼該功能函數就不對象獨有的功能
- 2、將功能函數體代碼放在類中,但是類中的函數體功能,只要是此類產生的對象都可調用
解決方法:
- 定義在類中的功能,預設就是給類產生的對象使用的,只要是此類產生的對象都可以使用
- 需要在功能函數形參數內填入self,之後只需要用類名’點‘函數名的方式,函數參數內填入調用對象名,就可直接使用該功能
class Student:
# 對象公用的數據
school_name = '清華大學'
# 專門給學生添加獨有數據的功能
def __init__(self, name, age, hobby):
self.__dict__['name'] = name
self.__dict__['age'] = age
self.__dict__['hobby'] = hobby
# 對象公共的功能
def choice_course(self):
print('學生選課功能')
stu1 = Student()
Student.choice_course(stu1)
5、補充知識
1、對象數據值修改
# 只需要使用對象‘點’的數據綁定的變數名的方式重新賦值即可
stu1.name = 'zhaozhao'
# 當名字不存在的情況下,將直接新增數據
stu1.paw = 123