網(wǎng)站首頁 編程語言 正文
什么是面向?qū)ο缶幊?類)
利用(面向)對象的(屬性和方法)去進行編碼的過程即面向?qū)ο缶幊?/p>
自定義對象數(shù)據(jù)類型就是面向?qū)ο笾械念?class)的概念
類的關(guān)鍵字 - class
class 關(guān)鍵字用來聲明類,類的名稱首字母大寫,多單詞的情況下每個單詞首字母大寫(即駝峰命名法)。在我們一開始學(xué)習(xí) Python 的時候說過,要盡量避免使用 駝峰命名法 ,但 類 的命名是一個特例,類 的命名可以使用駝峰命名。
類的定義與使用
類的定義示例如下:
class Nmae(object): # class關(guān)鍵字 + 類名(首字母大寫) + 小括號(括號內(nèi)填寫 object:為python中的通用對象,書寫通用對象的 class 會帶有更多的內(nèi)置功能) + 冒號 變量 = 變量的值 # 可以定義 類 的變量 def func(self): do # 也可以定義 類 的函數(shù):類函數(shù)內(nèi)有個必傳參數(shù) 'self' ,一定要書寫在類函數(shù)的第一參數(shù)位,這是 python 內(nèi)部的語法規(guī)定 # 需要注意的是 類的屬性與函數(shù)的縮進要統(tǒng)一
類的使用示例如下:
# 定義一個動物類;動物類中定義一個變量;定義一個 跑 的函數(shù)(屬性) class Animal(object): # 定義一個類 name = '哈士奇' # 類變量(類屬性) def run(self): # 類函數(shù):將 self 作為第一個參數(shù)傳入 類函數(shù) 'run()' print(f'{self.name} can run') # 'self.name'為類屬性,如果不加上'self.'則不會找到類屬性;如果想要在類函數(shù)中調(diào)用類屬性就必須加上'self.' # 'self' 參數(shù)具備兩個功能 # 1.可以幫助我們調(diào)用類屬性 # 2.將使用 self 的函數(shù)調(diào)用到類中,如果我們有另一個函數(shù),可以在另一個函數(shù)中通過 'self.' 來進行調(diào)用 run 函數(shù) dog = Animal() # 類的實例化 print(dog.name) # 通過實例化進行屬性調(diào)用 dog.run() # 通過實例化,進行函數(shù)調(diào)用 # >>> 執(zhí)行結(jié)果如下: # >>> 哈士奇 # >>> 哈士奇 can run
類的參數(shù) - self
在類里面,所有實例方法都需要加 self 參數(shù),且排在第一個,有且僅有一個。
self 參數(shù)的含義 :在類中定義的方法,第一個參數(shù) self 指向調(diào)用該方法的實例對象,在方法中通過 self.屬性 這樣的形式訪問對象的實例屬性
- self 是 類函數(shù) 中的必傳參數(shù),且必須放在第一個參數(shù)位置
- self 是一個對象,它代表著實例化的變量自身
- self 可以直接通過點(.)來定義一個類變量 如 self.name = Neo ,如果在函數(shù)體內(nèi)定義變量可以通過 self + . +變量名 來進行賦值。
- self 中的變量與含有 self參數(shù)的函數(shù)可以在類中的任何一個函數(shù)內(nèi)隨意調(diào)用
- 非函數(shù)中定義的變量在定時的時候不需要使用 self
如何理解 self 參數(shù)
類比
- 如果把 類 比作造房子的圖紙
- 類實例化 后的對象是真正可以住的房子
- 根據(jù)一張圖紙(類),可以設(shè)計出成千上萬的房子(實例對象)
- 每個房子長相都是類似的(都有相同的實例屬性和實例方法),但它們都有各自的主人
- 如何區(qū)分不同的房子:通過 self 參數(shù),可以保證每個房子的主任僅能進入自己的房子(每個實例對象只能調(diào)用自己的實例屬性和實例方法)
重點
- 一個類可以產(chǎn)生多個實例對象,當(dāng)某個實例對象調(diào)用實例方法,該對象會把自身的引用作為第一個參數(shù)自動傳遞給該方法
- 換句話說:Python 會自動將實例方法的第一個參數(shù)指向調(diào)用該方法的對象
- 這樣,Python 解釋器就知道到底要執(zhí)行哪個對象的實例方法了
- 調(diào)用實例方法的時候,不需要手動為第一個參數(shù)傳值
可能大家還不是很理解,根據(jù)類的兩個關(guān)鍵要素屬性和方法,具體來使用self看看實際應(yīng)用效果:
class Persion(object): name = None age = None def run(self): print(f'{self.name} 的健身項目是\'跑步\'') def swim(self): print(f'{self.name} 的健身項目是\'游泳\'') neo = Persion() neo.name = 'Neo' neo.run() # >>> 執(zhí)行結(jié)果如下: # >>> Neo 的健身項目是'跑步'
我們再重新實例化一個對象,看看這個新的實例化對象是否同步了 neo.name
class Persion(object): name = None age = None def run(self): print(f'{self.name} 的健身項目是\'跑步\'') def swim(self): print(f'{self.name} 的健身項目是\'游泳\'') neo = Persion() neo.name = 'Neo' neo.run() jack = Persion() jack.run() # >>> 執(zhí)行結(jié)果如下: # >>> Neo 的健身項目是'跑步' # >>> None 的健身項目是'跑步'
從輸出結(jié)果可以看到 我們修改的 neo 實例化對象的對應(yīng)的 name 的值僅作用于自己的實例,而 Persion 類,與新的 jack 實例化對象并沒有受到影響。
所以即使使用新的對象進行實例化,還是需要新的實例化對象來修改類的屬性,來達到我們自己想要的效果。其實很好理解,都是人類,但是每個人的個體化都是不同的。所以他們擁有人類的共同屬性后 (name,age) ,也可以自定義自己的屬性。
現(xiàn)在我們的 Persion 類 定義了兩個屬性 'name' 與 'age' ,如果我們再添加一個屬性呢? ,其實是可以的。現(xiàn)在我們針對 'Jack' 增加一個自定義屬性 ,嘗試一下。
class Persion(object): name = None age = None def run(self): print(f'{self.name} 的健身項目是\'跑步\'') def swim(self): print(f'{self.name} 的健身項目是\'游泳\'') neo = Persion() neo.name = 'Neo' neo.run() jack = Persion() jack.top = 180 print('\'Jack\'的身高是', jack.top) # >>> 執(zhí)行結(jié)果如下 # >>> Neo 的健身項目是'跑步' # >>> 'Jack'的身高是 180 print('\'Neo\'的身高是', neo.top) # >>> 執(zhí)行結(jié)果如下: # >>> AttributeError: 'Persion' object has no attribute 'top'
從上面的 jack.top 與 neo.top 的自定義屬性,我們發(fā)現(xiàn)三件事。
1.實例化對象可以自定義屬性
2.每個實例化對象自己定義的屬性與其他實例化對象不通用。
3.Persion類在實例化對象之后,依然只有自己的兩個屬性 (name 和 age) ,實例化對象自定義的屬性僅作用于自己,并不影響 類 。
self 的解析與總結(jié)
說實話,關(guān)于 Python 中的 self 我一開始接觸的時候,也是給我搞的云里霧繞、五迷三道的…這里做個總結(jié),希望對同樣云里霧繞、五迷三道的童鞋有所幫助。
- Python 中 self 代表的是 類的示例 ; self 在定義類的方法時是必須有的,雖然在調(diào)用時不必傳入相應(yīng)的參數(shù)。
- Python 中 self 只有在針對 類 的情況下,才是有意義的。
- self 只能用在 python 類 的方法中。
具體的舉例說明如下:
屬性
關(guān)于屬性 - 1:如果變量定義在類下面而不是類的方法下面,那這個變量既是類的屬性也是類實例的屬性。
class Cat(object): eyes = '有2只眼睛' legs = '有4條腿' tail = '有1只尾巴' dragonLi = Cat() dragonLi.name = '貍花貓' dragonLi_eyes = dragonLi.eyes dragonLi_legs = dragonLi.legs dragonLi_tail = dragonLi.tail print(' 貓 ' + Cat.eyes, Cat.legs, Cat.tail) print(dragonLi.name, dragonLi_eyes, dragonLi_legs, dragonLi_tail) # >>> 執(zhí)行結(jié)果如下: # >>> 貓 有2只眼睛 有4條腿 有1只尾巴 # >>> 貍花貓 有2只眼睛 有4條腿 有1只尾巴
關(guān)于屬性 - 2:如果變量定義在類的方法下面,如果加了self,那這個變量就是類實例的屬性,不是類的屬性;如果沒有加self,這個變量只是這個方法的局部變量,既不是類的屬性也不是類實例的屬性。
class Cat(object): eyes = '有2只眼睛' legs = '有4條腿' tail = '有1只尾巴' def __init__(self): # 關(guān)于__init__() 會在下面的 '類的構(gòu)造器'有詳細講解 self.color_01 = '黃棕色' color_02 = '黑棕色' dragonLi = Cat() dragonLi_color_01 = dragonLi.color_01 print('貍花貓有兩種披毛顏色,一種是:', dragonLi_color_01) # >>> 執(zhí)行結(jié)果如下: # >>> 貍花貓有兩種披毛顏色,一種是: 黃棕色 dragonLi_color_02 = dragonLi.color_02 print('貍花貓有兩種披毛顏色,另一種是:', dragonLi_color_02) # >>> 執(zhí)行結(jié)果如下: # >>> AttributeError: 'Cat' object has no attribute 'color_02'.
方法
關(guān)于方法1:如果在類中定義函數(shù)時加了self,那這個函數(shù)是類實例的方法,而不是類的方法。
class Cat(object): def eat(self): print('愛吃魚') dragonLi = Cat() dragonLi.eat() # >>> 執(zhí)行結(jié)果如下: # >>> 愛吃魚 Cat.cat() # >>> 執(zhí)行結(jié)果如下: # >>> TypeError: Cat.eat() missing 1 required positional argument: 'self'
關(guān)于方法2:如果在類中定義函數(shù)時候沒有加self,那這個函數(shù)就只是類的方法,而不是類實例的方法。
class Cat(object): def eat(): print('愛吃魚') Cat.eat() # >>> 執(zhí)行結(jié)果如下: # >>> 愛吃魚 dragonLi = Cat() dragonLi.eat() # >>> 執(zhí)行結(jié)果如下: # >>> TypeError: Cat.eat() takes 0 positional arguments but 1 was given
小結(jié)
屬性:
- 如果變量定義在類下面而不是類的方法下面,那這個變量既是類的屬性也是類實例的屬性。
- 如果變量定義在類的方法下面,如果加了self,那這個變量就是類實例的屬性,不是類的屬性;如果沒有加self,這個變量只是這個方法的局部變量,既不是類的屬性也不是類實例的屬性。
方法:
- 如果在類中定義函數(shù)時加了self,那這個函數(shù)是類實例的方法,而不是類的方法。
- 如果在類中定義函數(shù)時候沒有加self,那這個函數(shù)就只是類的方法,而不是類實例的方法。
類的構(gòu)造函數(shù)
前面我們了解了 類的創(chuàng)建、類的屬性、類函數(shù)的使用方法,現(xiàn)在我們再來看看類的構(gòu)造函數(shù)。
什么是類的構(gòu)造函數(shù)? —> 構(gòu)造函數(shù)是類中的一種默認函數(shù),通過定義它可以在 類實例化 的同時,將參數(shù)傳入類中。(類似于函數(shù)執(zhí)行的時候可以傳一些參數(shù))
構(gòu)造函數(shù)的創(chuàng)建方法
重點:構(gòu)造函數(shù)依然要在 類 中定義
def __init__(self, a, b) # def關(guān)鍵字 + __init__ + 小括號(括號內(nèi)第一個傳入的依然是 self ,后面再跟上希望實例化時傳入的參數(shù)) self.a = a # 在構(gòu)造函數(shù)里,將參數(shù)綁定在 self 中,將變量通過 self 綁定之后,就可以在類的各個函數(shù)中進行調(diào)用了 self.b = b
構(gòu)造函數(shù)的用法,示例如下:
class Test(object): def __init__(self, a): # __init__ 構(gòu)造函數(shù)一定要寫在第一個,這是一個很好的編程規(guī)范 self.a = a def run(self): print(self.a) test = Test(1) test.run() # >>> 執(zhí)行結(jié)果如下: # >>> 1 test_02 = Test('Hello') test_02.run() # >>> 執(zhí)行結(jié)果如下: # >>> Hello
接下來我們再使用 構(gòu)造函數(shù) 針對前面我們創(chuàng)建的 Cat 類進行修改
class Cat(object): def __init__(self, eyes, legs, tail, color='黃棕色'): self.eyes = eyes self.legs = legs self.tail = tail self.color = color def show_cat(self): self.work = '抓老鼠' print('貓的通用屬性為', self.eyes, self.legs, self.tail) dragonLi = Cat('2只眼睛', '4條腿', '1只尾巴') dragonLi.show_cat() # >>> 執(zhí)行結(jié)果如下: # >>> 貓的通用屬性為 2只眼睛 4條腿 1只尾巴 黃棕色 dragonLi.name = '貍花貓' dragonLi.color = '虎斑色' print(dragonLi.name, dragonLi.eyes, dragonLi.legs, dragonLi.tail, dragonLi.color, dragonLi.work) # >>> 執(zhí)行結(jié)果如下: # >>> 貍花貓 2只眼睛 4條腿 1只尾巴 虎斑色 抓老鼠
關(guān)于對象的生命周期
注意:這里說的對象的生命周期,指的是實例化的對象。
之前我們提到過,當(dāng)一個變量不使用的時候就會被內(nèi)存管家清理掉。 接下來我們就來看看一個變量的一生,從出現(xiàn)到消亡的過程。之所以在這里插上這一章節(jié)介紹 對象的生命周期 ,也是為了更好的理解對象, 從而更好的使用他們。
我們之前學(xué)習(xí)的 深拷貝與淺拷貝, 淺拷貝是創(chuàng)建一個新的內(nèi)存地址, 而深拷貝是使用之前已經(jīng)定好的變量。
通過對一個對象的生命周期的理解, 可以讓我們權(quán)衡是終結(jié)一個對象還是繼續(xù)使用它們。
我們通過構(gòu)造函數(shù)完成一個對象的實例化,這個時候一個對象的生命周期就開始了,在這個時候內(nèi)存管家發(fā)現(xiàn)有一個對象的加入就會為這個實例化的對象分配一個內(nèi)存地址(也就是實例化對象在內(nèi)存中的家)。
接下里我們就可以操作這個對象,可以調(diào)用它的內(nèi)置函數(shù)還有功能。當(dāng)我們不使用這個對象的時候,一般有兩種情況;
第一種是這個內(nèi)存塊中的值沒有變量與之綁定了,比如當(dāng)我們的一個變量的默認值被一個函數(shù)調(diào)用后變量有了新的值,這個時候變量原有的默認值與變量不再是賦值關(guān)系了。
第二種是當(dāng)我們執(zhí)行完了所有的程序,也就是代碼已經(jīng)執(zhí)行到了最后一行。 Python 解釋器發(fā)現(xiàn)已經(jīng)處理完了所有的業(yè)務(wù),這個時候腳本就會停止處理并釋放腳本中所有的對象,釋放所有的對象其實就是告知內(nèi)存管家,內(nèi)存管家就會自動處理這些對象的內(nèi)存地址。
以上兩種情況的統(tǒng)一表現(xiàn)形態(tài)都是不再使用這些對象,這個時候每個對象中自帶的內(nèi)置函數(shù) __del__ (兩個下劃線)就會被調(diào)用,通知內(nèi)存管家從內(nèi)存中釋放每個對象對應(yīng)的內(nèi)存塊。這就是整個對象的生命周期。
無論是字符串、數(shù)字、列表、元組、字典、集合,甚至布爾類型與空類型,我們知道 Python 中一切皆是對象,所以它們也是按照這個規(guī)律存在于消亡。
Python 中的內(nèi)存管理都是自動去完成的,所以我們并不需要特意的去對它進行專門的處理。
關(guān)于 __del__ 函數(shù)并不需要我們書寫和定義,當(dāng)我們實例化一個對象之后,它就會默認存在,并擁有自動通知內(nèi)存管家清理內(nèi)存的功能。這也是 Python 的特點之一。
原文鏈接:https://blog.csdn.net/weixin_42250835/article/details/123363958
相關(guān)推薦
- 2022-09-15 python實現(xiàn)簡單的計算器功能_python
- 2022-03-24 Android繪制平移動畫的示例代碼_Android
- 2023-05-29 docker部署xxl-job-admin出現(xiàn)數(shù)據(jù)庫拒絕問題及解決方法_docker
- 2023-07-02 Oracle中分析函數(shù)over()的用法及說明_oracle
- 2022-04-10 Windows Terminal添加到右鍵菜單中
- 2022-12-24 詳解C#?parallel中并行計算的四種寫法總結(jié)_C#教程
- 2022-05-01 LINQ操作符SelectMany的用法_C#教程
- 2022-09-26 ASP.NET?Core?6最小API中使用日志和DI示例詳解_ASP.NET
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支