一、面向物件
什么是面向物件?
面向物件是一門編程思想!
面向程序編程思想與面向物件編程思想對比:
- 面向程序編程思想:
核心是 “程序”二字,程序是指解決問題的步驟,即先干什么再干什么!
基于該編程思想撰寫程式,就好比在設計一條工廠流水線,一種機械式的思維方式
優點:
將復雜的問題流程化,進而簡單化
缺點:
牽一發而動全身,程式的可擴展性差
- 面向物件編程思想:
核心是 “物件” 二字,物件指的是“特征與技能”的結合體,
基于該編程思想撰寫程式,就好比把自己當做一個上帝在創造世界,一種“上帝式”的思維方式
優點:
可擴展性高
缺點:
面向物件撰寫程式的復雜程度比面向程序高
注意:編程思想僅僅是一門思想,與任何技術無關
二、類
1、什么是類?
類指的是型別、類別,
在兩種角度去看待類:
- 現實世界中:
- 先有一個個物件,經過社會的文明發展,隨之總結出類,物件是實際存在的,而類是抽象產生的
- python程式中:
- 必須先由類,再通過呼叫類產生物件
物件指的是“特征與技能”的結合體, 類指的是一系列“物件之間相同的特征與技能”的結合體
2、如何定義類?
如何寫類并產生物件:
- 先從現實世界中通過一個個物件總結出類
- 然后再定義類,后呼叫產生物件,
比如 “選課系統”:
選課系統 - 學生類:
- 學生物件1:
特征:
- 姓名:tank
- 性別:female
- 年齡:95
- 學校:家里蹲
技能:
- 技術:python
- 學習:learn
- 選課:course
- 學生物件2
特征:
- 姓名:jason
- 性別:female
- 年齡:99
- 學校:家里蹲
技能:
- 技術:python
- 學習:learn
- 選課:course
3、定義類的語法
語法:
class 關鍵字:幫你產生類
class 類名:
- 物件之間相同的特征
- 學校
school = "家里蹲"
- 物件之間相同的技能
- python
def Python():
pass
- learn
def Learn():
pass
- course
def Course():
pass
類名的規范:
- 駝峰命名法(推薦)
定義一個學生類并對屬性進行增刪查改:
# 定義一個家里蹲學生類
class JldStudent: # 類名指向的是類的記憶體地址
# 學生相同的特征
# 在類中的特征(即變數)稱之為“屬性”
school = "OldBoy"
# 注意:在類內部定義函式,會默認產生一個引數self
# 學生相同的技能(即函式)稱之為“方法”
def learn(self): # self此處當做一個形參
print("learning...")
# 查看類的名稱空間
print(JldStudent.__dict__)
print(JldStudent.__dict__["school"]) # 可呼叫屬性
print(JldStudent.__dict__["learn"]) # 獲取learn方法物件
JldStudent.__dict__["learn"](123) # 方法物件+(),相當于執行learn函式(方法)
# 類提供了一種特殊獲取名字的方式 “類名.名字”的方式
# 查
print(JldStudent.school)
JldStudent.learn(12)
# 改
JldStudent.school = "Cld"
print(JldStudent.school)
# 刪
del JldStudent.school
# print(JldStudent.school) # AttributeError: type object 'JldStudent' has no attribute 'school'
# 增
JldStudent.age = 18
print(JldStudent.age)
執行結果:
{'__module__': '__main__', 'school': 'OldBoy', 'learn': <function JldStudent.learn at 0x0000026D35CD97B8>, '__dict__': <attribute '__dict__' of 'JldStudent' objects>, '__weakref__': <attribute '__weakref__' of 'JldStudent' objects>, '__doc__': None}
OldBoy
<function JldStudent.learn at 0x0000026D35CD97B8>
learning...
OldBoy
learning...
Cld
18

4、類的名稱空間
- 類的名稱空間:
在定義階段時產生,會將類中所有的名字,扔進類的名稱空間
- 函式的名稱空間:
在呼叫函式時產生,函式呼叫結束后銷毀
三、物件
1、物件的產生
物件名=類名() ---> 呼叫類產生物件
類的名稱空間在定義時產生,物件的名稱空間在呼叫類時產生
呼叫類產生物件的程序稱之為類的實體化,物件稱之為一個類的實體
定義一個類:
class Student:
# 學校 ---> 屬性
school = "Jld"
# 技能 ---> 方法
def learn(self):
print(self) # 列印輸出為 <__main__.Student object at 0x00000000021B6248>,是一個物件
print("learning...")
# 獲取物件,產生物件
obj = Student()
print(obj) # 列印輸出為 <__main__.Student object at 0x00000000021B6248>,也是一個物件
# 物件呼叫類內部的名字(屬性)
print(obj.school)
# 物件呼叫類內部的函式(方法),無需傳入引數:會將物件當做第一個引數傳給該函式(方法)
obj.learn() # 物件的系結方法,無需傳參
執行結果:
<__main__.Student object at 0x000001BE191C6908>
Jld
<__main__.Student object at 0x000001BE191C6908>
learning...
由物件來呼叫類內部的函式,稱之為物件的系結方法,
物件的系結方法特殊之處:會將物件當做第一個引數自動傳給該函式(方法),所以物件呼叫類內部的函式時無需傳參
2、為物件添加獨有的屬性
定義一個類:
class Student: # 學校 --> 屬性 school = "Jld" def __init__(self, name, sex, age): # 引數:obj1, "張三", "female", 84 print(self.__dict__) # 給物件添加新的屬性 self.name = name # stu1.name = "張三" self.sex = sex # stu1.sex = "female" self.age = age # stu1.age = 84 print(self.__dict__) # 技能 ---> 方法 def learn(self): print("learning...") # obj1 = Student() # Student(obj1) ---> __init__(self) ---> self==obj1 # obj2 = Student() # Student(obj2) ---> __init__(self) ---> self==obj2 # obj3 = Student() # Student(obj3) ---> __init__(self) ---> self==obj3
# 給物件添加獨有的屬性: # 第一種方法(很麻煩):呼叫類后,為物件傳入物件獨有的特征(屬性) obj1.name = "張三" obj1.sex = "female" obj1.age = 84 # 第二種方法:呼叫類時,為物件傳入物件獨有的特征(屬性) # __init__(self, name, sex, age):obj1 --> self "張三" --> name "female" --> sex 84 --> age # 呼叫類時:會將物件當做第一個引數,并與括號內所有的引數一并傳給__init__() obj1 = Student("張三", "female", 84)
執行結果:
{}
{'name': '張三', 'sex': 'female', 'age': 84}
注意:凡是在類內部定義的.__或者__結尾的方法都有特殊意義
__init__():在類內部定義的方法,在呼叫類時觸發,會自動將物件當做第一個引數自動傳入并執行
3、物件名字的查找順序
物件名字的查找順序:
① 物件.屬性,會先找物件自己的
② 若物件沒有,會去找類的
③ 物件沒有,類也沒有,就會報錯
定義一個類:
class people:
country = "China"
name = "李四"
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
def run(self):
print("running...")
obj1 = people("張三", "female", 95)
print(obj1.name) # 張三 找物件自己的name屬性
print(obj1.country) # China 物件沒有,找類中的屬性
# 報錯:AttributeError: 'people' object has no attribute 'json'
print(obj1.json) # 物件沒有,類也沒有,就報錯
4、一切皆物件
在python中一切皆物件
"""
在python中一切皆物件
"""
class foo:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
# 產生物件
# 呼叫類產生物件的程序稱之為類的實體化,物件稱之為一個類的實體
foo_obj = foo(10, 20, 30)
print(foo_obj)
# 查看 字串 型別
print(type(str)) # <class 'type'>
# 查看 串列 型別
print(type(list)) # <class 'type'>
# 查看 字典 型別
print(type(dict)) # <class 'type'>
# 查看 元組 型別
print(type(tuple)) # <class 'type'>
# 查看 浮點型 型別
print(type(float)) # <class 'type'>
# 查看 整型 型別
print(type(int)) # <class 'type'>
# 查看 布林值 型別
print(type(bool)) # <class 'type'>
# 除了這些還有很多都是類,既然是類,就可以是物件,所以在python中一切皆物件
執行結果:
<__main__.foo object at 0x0000014471D71C88>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
四、根據面向物件編程撰寫一個“人狗大作戰”例子
"""
需求:有一個人物件,狗物件,狗咬人,人打狗
- 物件人1
- 特征
- 生命:1000
- 名字:name = "張三"
- 攻擊力:arg
- 技能
- 打:hit
- 物件人2
- 特征
- 生命:950
- 名字:name = "李四"
- 攻擊力:arg
- 技能
- 打:hit
- 抽象出類
- 人類:
- 相同特征
- 生命
- 相同特征
- 打
- 狗物件1
- 特征
- 生命值:150
- 名字:name = "二哈"
- 品種:dog_type = "哈士奇"
- 攻擊力:arg
- 技能
- 咬:bite
- 狗物件2
- 特征
- 生命值:250
- 名字:name = "小短腿"
- 品種:dog_type = "柯基"
- 攻擊力:arg
- 技能
- 咬:bite
- 抽象出類
- 狗類:
- 相同特征
- 生命
- 相同特征
- 咬
"""
import time
# 人類
class People:
def __init__(self, name, life, arg):
self.name = name
self.life = life
self.arg = arg
# 人物件呼叫hit時,傳入狗物件
def hit(self, dog_obj):
print(f"[{self.name}]要開始打[{dog_obj.name}]了")
# 減掉狗物件的生命值 值為人物件的攻擊力
dog_obj.life -= self.arg
print(f"[{dog_obj.name}]的生命值減掉:[{self.arg}],剩余血量為:[{dog_obj.life}]")
if dog_obj.life <= 0:
print(f"[{dog_obj.name}]已經沒了")
return True
# 狗類
class Dogs:
def __init__(self, name, life, dog_type, arg):
self.name = name
self.life = life
self.dog_type = dog_type
self.arg = arg
# 狗物件呼叫bite時,傳入人物件
def bite(self, p_obj):
print(f"[{self.name}]要開始咬[{p_obj.name}]了")
# 減掉人物件的生命值 值為狗物件的攻擊力
p_obj.life -= self.arg
print(f"[{p_obj.name}]的生命值減掉:[{self.arg}],剩余血量為:[{p_obj.life}]")
if p_obj.life <= 0:
print(f"[{p_obj.name}]已經沒了")
return True
p1 = People("張三", 1000, 50) # 人物件
d1 = Dogs("二哈", 150, "哈士奇", 200) # 狗物件
while True:
# 開始狗咬人,人打狗
res1 = d1.bite(p1)
if res1:
break
time.sleep(1) # 休眠1秒
res2 = p1.hit(d1)
if res2:
break
time.sleep(1) # 休眠1秒
執行結果:
[二哈]要開始咬[張三]了
[張三]的生命值減掉:[200],剩余血量為:[800]
[張三]要開始打[二哈]了
[二哈]的生命值減掉:[50],剩余血量為:[100]
[二哈]要開始咬[張三]了
[張三]的生命值減掉:[200],剩余血量為:[600]
[張三]要開始打[二哈]了
[二哈]的生命值減掉:[50],剩余血量為:[50]
[二哈]要開始咬[張三]了
[張三]的生命值減掉:[200],剩余血量為:[400]
[張三]要開始打[二哈]了
[二哈]的生命值減掉:[50],剩余血量為:[0]
[二哈]已經沒了
五、面向物件總結
面向物件:
核心是“物件”,物件指的是特征與技能的結合體
基于該編程思想撰寫程式,就好比在創造世界,一種上帝式的思維方式
優點:
可擴展性強
缺點:
撰寫復雜難度較面向程序高
1、類的實體化:呼叫類的程序稱之為類的實體化,產生的物件也可以稱之為類的一個實體
呼叫類產生物件發生的事情:
① 會產生一個空物件的名稱空間
② 會自動觸發__init__,并且會將物件當做第一個引數傳入
③ 會將呼叫類括號內的引數一并傳給__init__()
# 定義一個類
class People:
national = "han"
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 注意:看到self就應該知道是物件本身,在這里就是下面代碼中的p_obj物件
def learn(self):
print("learning...")
p_obj = People("張三", 184, "female")
print(p_obj.name, p_obj.age, p_obj.sex)
執行結果:
張三 184 female
2、查看類與物件的名稱空間:類.__dict__ 物件.__dict__
# 使用上面People類執行下列代碼
print(People.__dict__) # 查看類的名稱空間
print(p_obj.__dict__) # 查看物件的名稱空間
執行結果:
{'__module__': '__main__', 'national': 'han', '__init__': <function People.__init__ at 0x000001B4D9BC96A8>, 'learn': <function People.learn at 0x000001B4D9BC9620>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
{'name': '張三', 'age': 184, 'sex': 'female'}
3、類或物件的屬性操作:增、刪、查、改
# 使用上面People類執行下列代碼
# 類的屬性操作
People.sal = 3000 # 增
People.number = 1 # 增
del People.number # 刪
People.sal = 4500 # 改
print(People.sal) # 查
# 物件的屬性操作
p_obj.county = "China" # 增
del p_obj.sex # 刪
p_obj.name = "李四" # 改
print(p_obj.name) # 查
執行結果:
4500
李四
4、類中資料屬性(類中的變數):類中的屬性是給物件使用的,物件參考類中的屬性,指向的都是類中同一個記憶體地址
# 使用上面People類執行下列代碼
p_obj1 = People("王五", 84, "female")
p_obj2 = People("趙六", 85, "male")
p_obj3 = People("孫七", 86, "female")
print(p_obj1.national, id(p_obj1))
print(p_obj2.national, id(p_obj2))
print(p_obj3.national, id(p_obj3))
執行結果:
han 2612115777632
han 2612115777744
han 2612115777800
5、類中的方法(類中的函式):類中的方法是給物件使用的,由物件來呼叫就會將方法系結給不同的物件,并且會將物件當做第一個物件傳入
# 使用上面People類執行下列代碼
p_obj1 = People("王五", 84, "female")
p_obj2 = People("趙六", 85, "male")
p_obj3 = People("孫七", 86, "female")
print(People.learn)
print(p_obj1.learn)
print(p_obj2.learn)
print(p_obj3.learn)
執行結果:
<function People.learn at 0x0000022590CA9620>
<bound method People.learn of <__main__.People object at 0x0000022590CBA860>>
<bound method People.learn of <__main__.People object at 0x0000022590CBA8D0>>
<bound method People.learn of <__main__.People object at 0x0000022590CBA908>>
6、物件屬性的查找順序:先從物件自己的名稱空間找 ---> 類的名稱空間查找
# 使用上面People類執行下列代碼
print(p_obj1.national) # 從類中查找
print(p_obj1.national2) # 類中也沒有,報錯
7、物件系結方法的特殊之處
① 會將物件當做第一個引數傳入
② 若物件的系結發放中還有其他引數,會一并傳入,
8、一切皆物件:在python3中,類即型別
# 使用上面People類執行下列代碼
print(type(p_obj)) # <class '__main__.People'>
str1 = "orange"
print(type(str1)) # <class 'str'>
list1 = [1, 2, 3]
print(type(list1)) # <class 'list'>
執行結果:
<class '__main__.People'>
<class 'str'>
<class 'list'>
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/188308.html
標籤:其他
上一篇:Python流程控制陳述句
下一篇:小白 求助~!
