?本篇可樂和大家一起來吃透 Python 的面向物件,類和實體,
面向物件(OOP)
解釋:面向物件它是一種編程的思想,將現實事物抽象化為編程物件,
舉例說明:喝可樂
① 選擇自己根據配方買對應的材料然后制作可樂,最后喝可樂,
② 自己去小賣部直接買可樂喝,
第一種屬于面向程序(對應到編程當中,也就是每一個步驟都需要一步一步實作)
第二種就是面向物件,我們并不需要知道每一步是如何實作的,只需要知道最后能夠喝可樂即可,
一、類
解釋:類是面向物件的重要組成部分,類是對相同特征和行為事物的統稱,是一個抽象的概念,
? 語法
class 類名:
實際代碼
? 舉例:以人為例子
# 人有眼睛,鼻子,嘴巴這些特征,可以玩電腦,走路這些行為,
# 代碼如下:
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print("我會玩電腦")
?
def walk(self):
print("我會走路")
?
# self:下面會細講,并用代碼演示
二、物件
解釋:物件是類創建出來真實存在的事物,物件又可以稱為實體,
? 語法
物件名 = 類名()
? 舉例:以上述人為例子
人是一個抽象的概念,并不能代表實實在在的事物,但是可樂和在座的各位同學都是實際存在的事物,我們都屬于人,
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print("我會玩電腦")
?
def walk(self):
print("我會走路")
# 創建 kele 物件
kele = Person()
2.1 呼叫物件方法
? 語法
物件.方法名(引數)
?? 舉例
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print("我會玩電腦")
?
def walk(self):
print("我會走路")
?
# 創建 kele 物件
kele = Person()
kele.play_computer()
?
# 輸出 我會玩電腦
? 解釋實體方法中的 self 是什么
先上代碼
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print("我會玩電腦")
?
def eye(self):
print(self.eyes)
self.eyes = "卡茲然大眼睛"
print(self.eyes)
?
?
kele = Person()
kele.eye()
?
# 輸出結果是 眼睛 卡茲然大眼睛
?
?
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print("我會玩電腦")
?
def eye(self):
pass
?
?
kele = Person()
print(kele.eyes)
kele.eyes = "卡茲然大眼睛"
print(kele.eyes)
?
# 輸出 眼睛 卡茲然大眼睛
到這里可能有一部分同學已經明白 self 實際上是個什么東東了,為了更加通俗易懂,可樂再舉一個例子:
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print(f"self是{self}")
?
kele = Person()
kele.play_computer()
print(f"kele是{kele}")
結果:

根據上述兩個示例,我們可以知道 self 實際上就是類創建出來的實體物件,
? 物件在呼叫方法的時候不需要手動傳 self 值,因為 python 解釋器會自動將實體參考傳遞給 self ,
2.2 獲取物件屬性
解釋:屬性就是特征,例如:人的手,人的鼻子,人的身高,人的體重,
? 語法
① 物件名.屬性名 (這種在類外部使用)
② self.屬性名 (這種在類內部使用)
? 舉例1:還是以人為例子
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print(f"self是{self}")
?
?
kele = Person()
print(kele.nose)
?
# 輸出 鼻子
? 舉例2
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def get_nose(self):
print(self.nose)
?
?
kele = Person()
kele.get_nose()
?
# 輸出 鼻子
2.3 修改/設定物件屬性
? 語法
① 物件名.屬性名 = 值 (這種在類外部使用)
② self.屬性名 = 值 (這種在類內部使用)
? 舉例1:依舊以人為例子
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def play_computer(self):
print(f"self是{self}")
?
?
kele = Person()
kele.nose = "卡茲然大鼻子"
print(kele.nose)
?
# 輸出 卡茲然大鼻子
? 舉例2
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
def modify_nose(self):
self.nose = "卡茲然大鼻子"
?
?
kele = Person()
kele.modify_nose()
print(kele.nose)
?
# 輸出 卡茲然大鼻子
2.4 魔法方法
解釋:所謂的魔法方法也就是 python 內部已經提供的方法,他們的表現形式是 xxx ,
2.4.1 魔法方法 init
解釋 init 方法它是用于物件生成之后進行初始化的函式,不需要程式員手動呼叫,python 解釋器會在物件創建之后自動呼叫,
例如:人與生俱來就有嘴巴,鼻子,眼睛,那么我們在構造類的時候,就可以將這些屬性放進 init 方法中,
? 舉例
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
print(self.eyes)
?
?
kele = Person()
?
# 輸出 眼睛
? 他并不需要程式員手動呼叫,
2.4.2 魔法方法 new
解釋:我們之前一直在說物件是由類創建出來的,那么類又是怎么創建出來的呢?就是通過 new 方法,這個方法的功能就是創建物件,
? 如何通過 new 方法實作單例
解釋:所謂的單例就是一個類創建出來的物件都是相同的,
在默認情況下類創建出來的各個物件都是不一樣的,如果我們想一個類創建出來的物件都是一樣的,那該怎么做呢?答案就是通過 new 方法,
? 類創建不同的物件代碼
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
?
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)
結果如圖:

? 單例代碼
class Person:
instance = None
?
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super(Person, cls).__new__(cls, *args, **kwargs)
return cls.instance
?
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
?
?
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)
先貼出結果:

解釋一下代碼:
具體代碼在下面講解完繼承,類屬性,類方法之后就知道什么含義了,可樂先講一下代碼的大致意思:用變數 instance 存盤物件的記憶體地址,開始時只為 None ,當第一個物件創建之后,將該記憶體地址賦值給 instance 變數,后續的物件創建時判斷變數 instance 是否有值了,如果有,那么將之前的物件地址給新物件,這樣就保證了,后續的物件都和第一個物件的記憶體地址一樣,即該類創建出來的物件都是同一個,
2.5 類屬性
解釋:類物件所擁有的屬性,該類創建出來的所有物件共享同一個類屬性,類屬性在記憶體中只會有一個副本,
? 使用場景
如果在一個類中所有的物件都有一個共同的屬性,并且這個屬性的值是一樣的,那么我們就可以將屬性設定為類屬性,如果這個屬性的值每個物件都有其自己的含義,那么我們可以將其定義為實體屬性,
? 語法
在類里面 屬性名 = 值
? 舉例
class Person:
nose = "鼻子"
?
def __init__(self, name):
self.name = name
?
?
kele1 = Person("可樂1號")
kele2 = Person("可樂2號")
2.5.1 獲取類屬性
? 語法
① cls.屬性名 (在類里面)
② 類.屬性名 (在類外面)
③ 實體.屬性名 (在類外面)
? 舉例
class Person:
nose = "鼻子"
?
kele = Person()
?
print(kele.nose)
print(Person.nose)
?
# 輸出 鼻子 鼻子
2.5.2 修改類屬性的值
? 語法
① cls.屬性名 = 值 (在類里面)
② 類.屬性名 = 值 (在類外面)
? 不可用實體.屬性名 = 值來修改,這個含義代表添加實體屬性,
? 舉例
class Person:
nose = "鼻子"
?
Person.nose = "卡自然大鼻子"
print(Person.nose)
?
# 輸出 卡自然大鼻子
2.6 類方法
解釋:類方法是類物件所擁有的方法,用 @classmethod 來對方法進行修飾,
? 使用場景
類方法一般搭配類屬性來使用,常常用于對類屬性的修改,
? 語法
@classmethod
def 類方法名(cls):
? 舉例
class Person:
nose = "鼻子"
?
@classmethod
def add(cls):
pass
2.6.1 呼叫類方法
? 語法
① 類.類方法名 (在類外面)
② 實體.類方法名 (在類外面)
③ cls.類方法名 (在類里面)
? 舉例1
class Person:
nose = "鼻子"
?
@classmethod
def add(cls, nose):
cls.nose = nose
?
@classmethod
def update(cls):
cls.add("卡自然大鼻子")
?
?
Person.update()
print(Person.nose)
?
# 輸出 卡自然大鼻子
? 舉例2
class Person:
nose = "鼻子"
?
@classmethod
def update(cls):
cls.nose = "卡自然大鼻子"
?
?
Person.update()
print(Person.nose)
?
# 輸出 卡自然大鼻子
? 舉例3
class Person:
nose = "鼻子"
?
@classmethod
def update(cls):
cls.nose = "卡自然大鼻子"
?
kele = Person()
kele.update()
print(kele.nose)
?
# 輸出 卡自然大鼻子
2.7 靜態方法
解釋:靜態方法可以理解為就是普通的函式,只不過他的作用域限制于類里面,但是和類和實體本身并沒有多大的關系,他通過 @staticmethod 來修飾,
? 使用場景
如果想定義一個函式,但是該函式和類本身或者實體物件沒有多大關系,但是限制于該類中就可以使用靜態方法來定義,
? 舉例
class Person:
@staticmethod
def play_game():
print("可樂打游戲")
?
kele = Person()
kele.play_game()
?
# 輸出 可樂打游戲
三、面向物件三大特性
特性:封裝,繼承,多型,
3.1 封裝
解釋:將代碼寫到類里面即是封裝,并且封裝還可以給屬性或者方法設定權限,在上述代碼中已經使用了封裝的特性,
3.2 繼承
解釋:指的是類當中的從屬關系,子類自動擁有父類所有的屬性和方法,
? 所有的類都默認繼承Object類,
3.2.1 單繼承
單繼承:只繼承一個父類,
? 舉例
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Son(Father):
pass
?
?
son = Son()
son.get_name()
?
# 輸出 可樂家族
3.2.2 多繼承
多繼承:子類同時繼承多個父類,
? 舉例1
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Mother, Father):
pass
?
?
son = Son()
son.get_name()
?
# 輸出 媽媽家族
? 舉例2
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Father, Mother):
pass
?
?
son = Son()
son.get_name()
?
# 輸出 可樂家族
? 如果繼承的父類當中擁有相同的屬性或者方法,那么優先繼承第一個父類的屬性和方法,
3.2.3 mro確認繼承順序
繼承順序:如果一個類繼承多個父類,并且繼承關系比較復雜,那么我們可以使用內置方法 mro 來確定繼承順序,
? 舉例
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Mother, Father):
pass
?
?
print(Son.__mro__)
結果如圖:
3.2.4 重寫父類的方法
繼承中,支持子類對父類的方法進行重寫,
? 舉例
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Mother, Father):
?
def get_name(self):
print("子類重新方法")
?
?
son = Son()
son.get_name()
?
# 輸出 子類重新方法
3.2.5 繼承之super
super:子類重寫父類方法,但是還需要呼叫父類的其他方法或同名方法時,使用 super 可以不用關心繼承的是哪個父類,在語法上只需要填寫子類類名即可,
? 舉例1
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Mother, Father):
?
def get_name(self):
print("子類重新方法")
Mother.get_name(self)
Father.__init__(self)
Father.get_name(self)
?
?
son = Son()
son.get_name()
?
# 輸出 子類重新方法 媽媽家族 可樂家族
? 舉例2
class Father:
?
def __init__(self):
self.name = "可樂家族"
?
def get_name(self):
print(self.name)
?
?
class Mother:
?
def __init__(self):
self.name = "媽媽家族"
?
def get_name(self):
print(self.name)
super(Mother, self).__init__()
super(Mother, self).get_name()
?
def add_nose(self):
self.nose = "鼻子"
?
?
class Son(Mother, Father):
?
def get_name(self):
print("子類重新方法")
super(Son, self).get_name()
?
?
son = Son()
son.get_name()
?
# 輸出 子類重新方法 媽媽家族 可樂家族
? super 會自動查找父類,且順序遵循__mro__順序,適合單繼承使用;
? super 只能繼承最近的上一級父類,順序按照__mro__順序,
3.3 多型
解釋:不同的物件,有不同的結果,子類重寫父類的方法,并且呼叫不同的子類的相同父類方法,有不同的結果,
我們先上代碼來看:
class Person:
?
def get_sex(self):
print("人")
?
?
class Man(Person):
?
def get_sex(self):
print("男人")
?
?
class Women(Person):
?
def get_sex(self):
print("女人")
?
?
man = Man()
women = Women()
man.get_sex()
women.get_sex()
?
# 輸出 男人 女人
代碼解釋:
一個 Person 類中有一個父類公共方法 get_sex ,子類 man 和 women 通過重寫父類方法,產生不同的效果,這就是多型,那么多型有什么好處呢?多型可以使得代碼變得更加靈活,更通用,適應的業務場景多,
到此,我們在本篇中學習了 python 面向物件,各位同學在學習程序中遇到疑問可以私聊可樂,可樂看到了都會一一回復的,那么下一篇可樂將和大家看一下閉包,裝飾器和深拷貝,淺拷貝,謝謝大家的支持~~~

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264165.html
標籤:python
