Python學(xué)習(xí)之面向?qū)ο缶幊淘斀?/h1>
更新時(shí)間:2022年03月09日 09:54:59 作者:渴望力量的哈士奇
利用(面向)對(duì)象的(屬性和方法)去進(jìn)行編碼的過(guò)程即面向?qū)ο缶幊?。本文將通過(guò)示例詳細(xì)為大家介紹一下Python中的面向?qū)ο缶幊?,需要的可以參考一?/div>
什么是面向?qū)ο缶幊?類(lèi))
利用(面向)對(duì)象的(屬性和方法)去進(jìn)行編碼的過(guò)程即面向?qū)ο缶幊?/p>
自定義對(duì)象數(shù)據(jù)類(lèi)型就是面向?qū)ο笾械念?lèi)(class)的概念
類(lèi)的關(guān)鍵字 - class
class 關(guān)鍵字用來(lái)聲明類(lèi),類(lèi)的名稱(chēng)首字母大寫(xiě),多單詞的情況下每個(gè)單詞首字母大寫(xiě)(即駝峰命名法)。在我們一開(kāi)始學(xué)習(xí) Python 的時(shí)候說(shuō)過(guò),要盡量避免使用 駝峰命名法 ,但 類(lèi) 的命名是一個(gè)特例,類(lèi) 的命名可以使用駝峰命名。
類(lèi)的定義與使用
類(lèi)的定義示例如下:
class Nmae(object):
# class關(guān)鍵字 + 類(lèi)名(首字母大寫(xiě)) + 小括號(hào)(括號(hào)內(nèi)填寫(xiě) object:為python中的通用對(duì)象,書(shū)寫(xiě)通用對(duì)象的 class 會(huì)帶有更多的內(nèi)置功能) + 冒號(hào)
變量 = 變量的值
# 可以定義 類(lèi) 的變量
def func(self):
do
# 也可以定義 類(lèi) 的函數(shù):類(lèi)函數(shù)內(nèi)有個(gè)必傳參數(shù) 'self' ,一定要書(shū)寫(xiě)在類(lèi)函數(shù)的第一參數(shù)位,這是 python 內(nèi)部的語(yǔ)法規(guī)定
# 需要注意的是 類(lèi)的屬性與函數(shù)的縮進(jìn)要統(tǒng)一
類(lèi)的使用示例如下:
# 定義一個(gè)動(dòng)物類(lèi);動(dòng)物類(lèi)中定義一個(gè)變量;定義一個(gè) 跑 的函數(shù)(屬性)
class Animal(object): # 定義一個(gè)類(lèi)
name = '哈士奇' # 類(lèi)變量(類(lèi)屬性)
def run(self): # 類(lèi)函數(shù):將 self 作為第一個(gè)參數(shù)傳入 類(lèi)函數(shù) 'run()'
print(f'{self.name} can run')
# 'self.name'為類(lèi)屬性,如果不加上'self.'則不會(huì)找到類(lèi)屬性;如果想要在類(lèi)函數(shù)中調(diào)用類(lèi)屬性就必須加上'self.'
# 'self' 參數(shù)具備兩個(gè)功能
# 1.可以幫助我們調(diào)用類(lèi)屬性
# 2.將使用 self 的函數(shù)調(diào)用到類(lèi)中,如果我們有另一個(gè)函數(shù),可以在另一個(gè)函數(shù)中通過(guò) 'self.' 來(lái)進(jìn)行調(diào)用 run 函數(shù)
dog = Animal() # 類(lèi)的實(shí)例化
print(dog.name) # 通過(guò)實(shí)例化進(jìn)行屬性調(diào)用
dog.run() # 通過(guò)實(shí)例化,進(jìn)行函數(shù)調(diào)用
# >>> 執(zhí)行結(jié)果如下:
# >>> 哈士奇
# >>> 哈士奇 can run
類(lèi)的參數(shù) - self
在類(lèi)里面,所有實(shí)例方法都需要加 self 參數(shù),且排在第一個(gè),有且僅有一個(gè)。
self 參數(shù)的含義 :在類(lèi)中定義的方法,第一個(gè)參數(shù) self 指向調(diào)用該方法的實(shí)例對(duì)象,在方法中通過(guò) self.屬性 這樣的形式訪問(wèn)對(duì)象的實(shí)例屬性
- self 是 類(lèi)函數(shù) 中的必傳參數(shù),且必須放在第一個(gè)參數(shù)位置
- self 是一個(gè)對(duì)象,它代表著實(shí)例化的變量自身
- self 可以直接通過(guò)點(diǎn)(.)來(lái)定義一個(gè)類(lèi)變量 如 self.name = Neo ,如果在函數(shù)體內(nèi)定義變量可以通過(guò) self + . +變量名 來(lái)進(jìn)行賦值。
- self 中的變量與含有 self參數(shù)的函數(shù)可以在類(lèi)中的任何一個(gè)函數(shù)內(nèi)隨意調(diào)用
- 非函數(shù)中定義的變量在定時(shí)的時(shí)候不需要使用 self
如何理解 self 參數(shù)
類(lèi)比
- 如果把 類(lèi) 比作造房子的圖紙
- 類(lèi)實(shí)例化 后的對(duì)象是真正可以住的房子
- 根據(jù)一張圖紙(類(lèi)),可以設(shè)計(jì)出成千上萬(wàn)的房子(實(shí)例對(duì)象)
- 每個(gè)房子長(zhǎng)相都是類(lèi)似的(都有相同的實(shí)例屬性和實(shí)例方法),但它們都有各自的主人
- 如何區(qū)分不同的房子:通過(guò) self 參數(shù),可以保證每個(gè)房子的主任僅能進(jìn)入自己的房子(每個(gè)實(shí)例對(duì)象只能調(diào)用自己的實(shí)例屬性和實(shí)例方法)
重點(diǎn)
- 一個(gè)類(lèi)可以產(chǎn)生多個(gè)實(shí)例對(duì)象,當(dāng)某個(gè)實(shí)例對(duì)象調(diào)用實(shí)例方法,該對(duì)象會(huì)把自身的引用作為第一個(gè)參數(shù)自動(dòng)傳遞給該方法
- 換句話說(shuō):Python 會(huì)自動(dòng)將實(shí)例方法的第一個(gè)參數(shù)指向調(diào)用該方法的對(duì)象
- 這樣,Python 解釋器就知道到底要執(zhí)行哪個(gè)對(duì)象的實(shí)例方法了
- 調(diào)用實(shí)例方法的時(shí)候,不需要手動(dòng)為第一個(gè)參數(shù)傳值
可能大家還不是很理解,根據(jù)類(lèi)的兩個(gè)關(guān)鍵要素屬性和方法,具體來(lái)使用self看看實(shí)際應(yīng)用效果:
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
# >>> 執(zhí)行結(jié)果如下:
# >>> Neo 的健身項(xiàng)目是'跑步'
我們?cè)僦匦聦?shí)例化一個(gè)對(duì)象,看看這個(gè)新的實(shí)例化對(duì)象是否同步了 neo.name
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
jack = Persion()
jack.run()
# >>> 執(zhí)行結(jié)果如下:
# >>> Neo 的健身項(xiàng)目是'跑步'
# >>> None 的健身項(xiàng)目是'跑步'
從輸出結(jié)果可以看到 我們修改的 neo 實(shí)例化對(duì)象的對(duì)應(yīng)的 name 的值僅作用于自己的實(shí)例,而 Persion 類(lèi),與新的 jack 實(shí)例化對(duì)象并沒(méi)有受到影響。
所以即使使用新的對(duì)象進(jìn)行實(shí)例化,還是需要新的實(shí)例化對(duì)象來(lái)修改類(lèi)的屬性,來(lái)達(dá)到我們自己想要的效果。其實(shí)很好理解,都是人類(lèi),但是每個(gè)人的個(gè)體化都是不同的。所以他們擁有人類(lèi)的共同屬性后 (name,age) ,也可以自定義自己的屬性。
現(xiàn)在我們的 Persion 類(lèi) 定義了兩個(gè)屬性 'name' 與 'age' ,如果我們?cè)偬砑右粋€(gè)屬性呢? ,其實(shí)是可以的?,F(xiàn)在我們針對(duì) 'Jack' 增加一個(gè)自定義屬性 ,嘗試一下。
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
jack = Persion()
jack.top = 180
print('\'Jack\'的身高是', jack.top)
# >>> 執(zhí)行結(jié)果如下
# >>> Neo 的健身項(xiàng)目是'跑步'
# >>> 'Jack'的身高是 180
print('\'Neo\'的身高是', neo.top)
# >>> 執(zhí)行結(jié)果如下:
# >>> AttributeError: 'Persion' object has no attribute 'top'
從上面的 jack.top 與 neo.top 的自定義屬性,我們發(fā)現(xiàn)三件事。
1.實(shí)例化對(duì)象可以自定義屬性
2.每個(gè)實(shí)例化對(duì)象自己定義的屬性與其他實(shí)例化對(duì)象不通用。
3.Persion類(lèi)在實(shí)例化對(duì)象之后,依然只有自己的兩個(gè)屬性 (name 和 age) ,實(shí)例化對(duì)象自定義的屬性僅作用于自己,并不影響 類(lèi) 。
self 的解析與總結(jié)
說(shuō)實(shí)話,關(guān)于 Python 中的 self 我一開(kāi)始接觸的時(shí)候,也是給我搞的云里霧繞、五迷三道的…這里做個(gè)總結(jié),希望對(duì)同樣云里霧繞、五迷三道的童鞋有所幫助。
- Python 中 self 代表的是 類(lèi)的示例 ; self 在定義類(lèi)的方法時(shí)是必須有的,雖然在調(diào)用時(shí)不必傳入相應(yīng)的參數(shù)。
- Python 中 self 只有在針對(duì) 類(lèi) 的情況下,才是有意義的。
- self 只能用在 python 類(lèi) 的方法中。
具體的舉例說(shuō)明如下:
屬性
關(guān)于屬性 - 1:如果變量定義在類(lèi)下面而不是類(lèi)的方法下面,那這個(gè)變量既是類(lèi)的屬性也是類(lèi)實(shí)例的屬性。
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:如果變量定義在類(lèi)的方法下面,如果加了self,那這個(gè)變量就是類(lèi)實(shí)例的屬性,不是類(lèi)的屬性;如果沒(méi)有加self,這個(gè)變量只是這個(gè)方法的局部變量,既不是類(lèi)的屬性也不是類(lèi)實(shí)例的屬性。
class Cat(object):
eyes = '有2只眼睛'
legs = '有4條腿'
tail = '有1只尾巴'
def __init__(self): # 關(guān)于__init__() 會(huì)在下面的 '類(lèi)的構(gòu)造器'有詳細(xì)講解
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:如果在類(lèi)中定義函數(shù)時(shí)加了self,那這個(gè)函數(shù)是類(lèi)實(shí)例的方法,而不是類(lèi)的方法。
class Cat(object):
def eat(self):
print('愛(ài)吃魚(yú)')
dragonLi = Cat()
dragonLi.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> 愛(ài)吃魚(yú)
Cat.cat()
# >>> 執(zhí)行結(jié)果如下:
# >>> TypeError: Cat.eat() missing 1 required positional argument: 'self'
關(guān)于方法2:如果在類(lèi)中定義函數(shù)時(shí)候沒(méi)有加self,那這個(gè)函數(shù)就只是類(lèi)的方法,而不是類(lèi)實(shí)例的方法。
class Cat(object):
def eat():
print('愛(ài)吃魚(yú)')
Cat.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> 愛(ài)吃魚(yú)
dragonLi = Cat()
dragonLi.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> TypeError: Cat.eat() takes 0 positional arguments but 1 was given
小結(jié)
屬性:
- 如果變量定義在類(lèi)下面而不是類(lèi)的方法下面,那這個(gè)變量既是類(lèi)的屬性也是類(lèi)實(shí)例的屬性。
- 如果變量定義在類(lèi)的方法下面,如果加了self,那這個(gè)變量就是類(lèi)實(shí)例的屬性,不是類(lèi)的屬性;如果沒(méi)有加self,這個(gè)變量只是這個(gè)方法的局部變量,既不是類(lèi)的屬性也不是類(lèi)實(shí)例的屬性。
方法:
- 如果在類(lèi)中定義函數(shù)時(shí)加了self,那這個(gè)函數(shù)是類(lèi)實(shí)例的方法,而不是類(lèi)的方法。
- 如果在類(lèi)中定義函數(shù)時(shí)候沒(méi)有加self,那這個(gè)函數(shù)就只是類(lèi)的方法,而不是類(lèi)實(shí)例的方法。
類(lèi)的構(gòu)造函數(shù)
前面我們了解了 類(lèi)的創(chuàng)建、類(lèi)的屬性、類(lèi)函數(shù)的使用方法,現(xiàn)在我們?cè)賮?lái)看看類(lèi)的構(gòu)造函數(shù)。
什么是類(lèi)的構(gòu)造函數(shù)? —> 構(gòu)造函數(shù)是類(lèi)中的一種默認(rèn)函數(shù),通過(guò)定義它可以在 類(lèi)實(shí)例化 的同時(shí),將參數(shù)傳入類(lèi)中。(類(lèi)似于函數(shù)執(zhí)行的時(shí)候可以傳一些參數(shù))
構(gòu)造函數(shù)的創(chuàng)建方法
重點(diǎn):構(gòu)造函數(shù)依然要在 類(lèi) 中定義
def __init__(self, a, b) # def關(guān)鍵字 + __init__ + 小括號(hào)(括號(hào)內(nèi)第一個(gè)傳入的依然是 self ,后面再跟上希望實(shí)例化時(shí)傳入的參數(shù))
self.a = a # 在構(gòu)造函數(shù)里,將參數(shù)綁定在 self 中,將變量通過(guò) self 綁定之后,就可以在類(lèi)的各個(gè)函數(shù)中進(jìn)行調(diào)用了
self.b = b
構(gòu)造函數(shù)的用法,示例如下:
class Test(object):
def __init__(self, a): # __init__ 構(gòu)造函數(shù)一定要寫(xiě)在第一個(gè),這是一個(gè)很好的編程規(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
接下來(lái)我們?cè)偈褂?構(gòu)造函數(shù) 針對(duì)前面我們創(chuàng)建的 Cat 類(lèi)進(jìn)行修改
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)于對(duì)象的生命周期
注意:這里說(shuō)的對(duì)象的生命周期,指的是實(shí)例化的對(duì)象。
之前我們提到過(guò),當(dāng)一個(gè)變量不使用的時(shí)候就會(huì)被內(nèi)存管家清理掉。 接下來(lái)我們就來(lái)看看一個(gè)變量的一生,從出現(xiàn)到消亡的過(guò)程。之所以在這里插上這一章節(jié)介紹 對(duì)象的生命周期 ,也是為了更好的理解對(duì)象, 從而更好的使用他們。
我們之前學(xué)習(xí)的 深拷貝與淺拷貝, 淺拷貝是創(chuàng)建一個(gè)新的內(nèi)存地址, 而深拷貝是使用之前已經(jīng)定好的變量。
通過(guò)對(duì)一個(gè)對(duì)象的生命周期的理解, 可以讓我們權(quán)衡是終結(jié)一個(gè)對(duì)象還是繼續(xù)使用它們。
我們通過(guò)構(gòu)造函數(shù)完成一個(gè)對(duì)象的實(shí)例化,這個(gè)時(shí)候一個(gè)對(duì)象的生命周期就開(kāi)始了,在這個(gè)時(shí)候內(nèi)存管家發(fā)現(xiàn)有一個(gè)對(duì)象的加入就會(huì)為這個(gè)實(shí)例化的對(duì)象分配一個(gè)內(nèi)存地址(也就是實(shí)例化對(duì)象在內(nèi)存中的家)。
接下里我們就可以操作這個(gè)對(duì)象,可以調(diào)用它的內(nèi)置函數(shù)還有功能。當(dāng)我們不使用這個(gè)對(duì)象的時(shí)候,一般有兩種情況;
第一種是這個(gè)內(nèi)存塊中的值沒(méi)有變量與之綁定了,比如當(dāng)我們的一個(gè)變量的默認(rèn)值被一個(gè)函數(shù)調(diào)用后變量有了新的值,這個(gè)時(shí)候變量原有的默認(rèn)值與變量不再是賦值關(guān)系了。
第二種是當(dāng)我們執(zhí)行完了所有的程序,也就是代碼已經(jīng)執(zhí)行到了最后一行。 Python 解釋器發(fā)現(xiàn)已經(jīng)處理完了所有的業(yè)務(wù),這個(gè)時(shí)候腳本就會(huì)停止處理并釋放腳本中所有的對(duì)象,釋放所有的對(duì)象其實(shí)就是告知內(nèi)存管家,內(nèi)存管家就會(huì)自動(dòng)處理這些對(duì)象的內(nèi)存地址。
以上兩種情況的統(tǒng)一表現(xiàn)形態(tài)都是不再使用這些對(duì)象,這個(gè)時(shí)候每個(gè)對(duì)象中自帶的內(nèi)置函數(shù) __del__ (兩個(gè)下劃線)就會(huì)被調(diào)用,通知內(nèi)存管家從內(nèi)存中釋放每個(gè)對(duì)象對(duì)應(yīng)的內(nèi)存塊。這就是整個(gè)對(duì)象的生命周期。
無(wú)論是字符串、數(shù)字、列表、元組、字典、集合,甚至布爾類(lèi)型與空類(lèi)型,我們知道 Python 中一切皆是對(duì)象,所以它們也是按照這個(gè)規(guī)律存在于消亡。
Python 中的內(nèi)存管理都是自動(dòng)去完成的,所以我們并不需要特意的去對(duì)它進(jìn)行專(zhuān)門(mén)的處理。
關(guān)于 __del__ 函數(shù)并不需要我們書(shū)寫(xiě)和定義,當(dāng)我們實(shí)例化一個(gè)對(duì)象之后,它就會(huì)默認(rèn)存在,并擁有自動(dòng)通知內(nèi)存管家清理內(nèi)存的功能。這也是 Python 的特點(diǎn)之一。
以上就是Python學(xué)習(xí)之面向?qū)ο缶幊淘斀獾脑敿?xì)內(nèi)容,更多關(guān)于Python面向?qū)ο缶幊痰馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
-
Python+Pygame實(shí)現(xiàn)之走四棋兒游戲的實(shí)現(xiàn)
大家以前應(yīng)該都聽(tīng)說(shuō)過(guò)一個(gè)游戲:叫做走四棋兒。直接在家里的水泥地上用燒完的炭火灰畫(huà)出幾條線,擺上幾顆石頭子即可。當(dāng)時(shí)的火爆程度可謂是達(dá)到了一個(gè)新的高度。本文將利用Pygame實(shí)現(xiàn)這一游戲,需要的可以參考一下 2022-07-07
-
python有證書(shū)的加密解密實(shí)現(xiàn)方法
這篇文章主要介紹了python有證書(shū)的加密解密實(shí)現(xiàn)方法,采用了M2Crypto組件進(jìn)行相關(guān)的加密解密操作,包含了詳細(xì)的完整實(shí)現(xiàn)過(guò)程,需要的朋友可以參考下 2014-11-11
-
python實(shí)現(xiàn)從wind導(dǎo)入數(shù)據(jù)
今天小編就為大家分享一篇python實(shí)現(xiàn)從wind導(dǎo)入數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧 2019-12-12
-
Python從零開(kāi)始創(chuàng)建區(qū)塊鏈
這篇文章主要為大家詳細(xì)介紹了Python從零開(kāi)始創(chuàng)建區(qū)塊鏈的步驟
,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下 2018-03-03
-
gearman的安裝啟動(dòng)及python API使用實(shí)例
這篇文章主要介紹了gearman的安裝啟動(dòng)及python API使用,需要的朋友可以參考下 2014-07-07
-
淺談python中的getattr函數(shù) hasattr函數(shù)
下面小編就為大家?guī)?lái)一篇淺談python中的getattr函數(shù) hasattr函數(shù)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧 2016-06-06
-
快速排序的算法思想及Python版快速排序的實(shí)現(xiàn)示例
快速排序算法來(lái)源于分治法的思想策略,這里我們將來(lái)為大家簡(jiǎn)單解析一下快速排序的算法思想及Python版快速排序的實(shí)現(xiàn)示例: 2016-07-07
最新評(píng)論
什么是面向?qū)ο缶幊?類(lèi))
利用(面向)對(duì)象的(屬性和方法)去進(jìn)行編碼的過(guò)程即面向?qū)ο缶幊?/p>
自定義對(duì)象數(shù)據(jù)類(lèi)型就是面向?qū)ο笾械念?lèi)(class)的概念
類(lèi)的關(guān)鍵字 - class
class 關(guān)鍵字用來(lái)聲明類(lèi),類(lèi)的名稱(chēng)首字母大寫(xiě),多單詞的情況下每個(gè)單詞首字母大寫(xiě)(即駝峰命名法)。在我們一開(kāi)始學(xué)習(xí) Python 的時(shí)候說(shuō)過(guò),要盡量避免使用 駝峰命名法 ,但 類(lèi) 的命名是一個(gè)特例,類(lèi) 的命名可以使用駝峰命名。
類(lèi)的定義與使用
類(lèi)的定義示例如下:
class Nmae(object):
# class關(guān)鍵字 + 類(lèi)名(首字母大寫(xiě)) + 小括號(hào)(括號(hào)內(nèi)填寫(xiě) object:為python中的通用對(duì)象,書(shū)寫(xiě)通用對(duì)象的 class 會(huì)帶有更多的內(nèi)置功能) + 冒號(hào)
變量 = 變量的值
# 可以定義 類(lèi) 的變量
def func(self):
do
# 也可以定義 類(lèi) 的函數(shù):類(lèi)函數(shù)內(nèi)有個(gè)必傳參數(shù) 'self' ,一定要書(shū)寫(xiě)在類(lèi)函數(shù)的第一參數(shù)位,這是 python 內(nèi)部的語(yǔ)法規(guī)定
# 需要注意的是 類(lèi)的屬性與函數(shù)的縮進(jìn)要統(tǒng)一
類(lèi)的使用示例如下:
# 定義一個(gè)動(dòng)物類(lèi);動(dòng)物類(lèi)中定義一個(gè)變量;定義一個(gè) 跑 的函數(shù)(屬性)
class Animal(object): # 定義一個(gè)類(lèi)
name = '哈士奇' # 類(lèi)變量(類(lèi)屬性)
def run(self): # 類(lèi)函數(shù):將 self 作為第一個(gè)參數(shù)傳入 類(lèi)函數(shù) 'run()'
print(f'{self.name} can run')
# 'self.name'為類(lèi)屬性,如果不加上'self.'則不會(huì)找到類(lèi)屬性;如果想要在類(lèi)函數(shù)中調(diào)用類(lèi)屬性就必須加上'self.'
# 'self' 參數(shù)具備兩個(gè)功能
# 1.可以幫助我們調(diào)用類(lèi)屬性
# 2.將使用 self 的函數(shù)調(diào)用到類(lèi)中,如果我們有另一個(gè)函數(shù),可以在另一個(gè)函數(shù)中通過(guò) 'self.' 來(lái)進(jìn)行調(diào)用 run 函數(shù)
dog = Animal() # 類(lèi)的實(shí)例化
print(dog.name) # 通過(guò)實(shí)例化進(jìn)行屬性調(diào)用
dog.run() # 通過(guò)實(shí)例化,進(jìn)行函數(shù)調(diào)用
# >>> 執(zhí)行結(jié)果如下:
# >>> 哈士奇
# >>> 哈士奇 can run
類(lèi)的參數(shù) - self
在類(lèi)里面,所有實(shí)例方法都需要加 self 參數(shù),且排在第一個(gè),有且僅有一個(gè)。
self 參數(shù)的含義 :在類(lèi)中定義的方法,第一個(gè)參數(shù) self 指向調(diào)用該方法的實(shí)例對(duì)象,在方法中通過(guò) self.屬性 這樣的形式訪問(wèn)對(duì)象的實(shí)例屬性
- self 是 類(lèi)函數(shù) 中的必傳參數(shù),且必須放在第一個(gè)參數(shù)位置
- self 是一個(gè)對(duì)象,它代表著實(shí)例化的變量自身
- self 可以直接通過(guò)點(diǎn)(.)來(lái)定義一個(gè)類(lèi)變量 如 self.name = Neo ,如果在函數(shù)體內(nèi)定義變量可以通過(guò) self + . +變量名 來(lái)進(jìn)行賦值。
- self 中的變量與含有 self參數(shù)的函數(shù)可以在類(lèi)中的任何一個(gè)函數(shù)內(nèi)隨意調(diào)用
- 非函數(shù)中定義的變量在定時(shí)的時(shí)候不需要使用 self
如何理解 self 參數(shù)
類(lèi)比
- 如果把 類(lèi) 比作造房子的圖紙
- 類(lèi)實(shí)例化 后的對(duì)象是真正可以住的房子
- 根據(jù)一張圖紙(類(lèi)),可以設(shè)計(jì)出成千上萬(wàn)的房子(實(shí)例對(duì)象)
- 每個(gè)房子長(zhǎng)相都是類(lèi)似的(都有相同的實(shí)例屬性和實(shí)例方法),但它們都有各自的主人
- 如何區(qū)分不同的房子:通過(guò) self 參數(shù),可以保證每個(gè)房子的主任僅能進(jìn)入自己的房子(每個(gè)實(shí)例對(duì)象只能調(diào)用自己的實(shí)例屬性和實(shí)例方法)
重點(diǎn)
- 一個(gè)類(lèi)可以產(chǎn)生多個(gè)實(shí)例對(duì)象,當(dāng)某個(gè)實(shí)例對(duì)象調(diào)用實(shí)例方法,該對(duì)象會(huì)把自身的引用作為第一個(gè)參數(shù)自動(dòng)傳遞給該方法
- 換句話說(shuō):Python 會(huì)自動(dòng)將實(shí)例方法的第一個(gè)參數(shù)指向調(diào)用該方法的對(duì)象
- 這樣,Python 解釋器就知道到底要執(zhí)行哪個(gè)對(duì)象的實(shí)例方法了
- 調(diào)用實(shí)例方法的時(shí)候,不需要手動(dòng)為第一個(gè)參數(shù)傳值
可能大家還不是很理解,根據(jù)類(lèi)的兩個(gè)關(guān)鍵要素屬性和方法,具體來(lái)使用self看看實(shí)際應(yīng)用效果:
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
# >>> 執(zhí)行結(jié)果如下:
# >>> Neo 的健身項(xiàng)目是'跑步'
我們?cè)僦匦聦?shí)例化一個(gè)對(duì)象,看看這個(gè)新的實(shí)例化對(duì)象是否同步了 neo.name
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
jack = Persion()
jack.run()
# >>> 執(zhí)行結(jié)果如下:
# >>> Neo 的健身項(xiàng)目是'跑步'
# >>> None 的健身項(xiàng)目是'跑步'
從輸出結(jié)果可以看到 我們修改的 neo 實(shí)例化對(duì)象的對(duì)應(yīng)的 name 的值僅作用于自己的實(shí)例,而 Persion 類(lèi),與新的 jack 實(shí)例化對(duì)象并沒(méi)有受到影響。
所以即使使用新的對(duì)象進(jìn)行實(shí)例化,還是需要新的實(shí)例化對(duì)象來(lái)修改類(lèi)的屬性,來(lái)達(dá)到我們自己想要的效果。其實(shí)很好理解,都是人類(lèi),但是每個(gè)人的個(gè)體化都是不同的。所以他們擁有人類(lèi)的共同屬性后 (name,age) ,也可以自定義自己的屬性。
現(xiàn)在我們的 Persion 類(lèi) 定義了兩個(gè)屬性 'name' 與 'age' ,如果我們?cè)偬砑右粋€(gè)屬性呢? ,其實(shí)是可以的?,F(xiàn)在我們針對(duì) 'Jack' 增加一個(gè)自定義屬性 ,嘗試一下。
class Persion(object):
name = None
age = None
def run(self):
print(f'{self.name} 的健身項(xiàng)目是\'跑步\'')
def swim(self):
print(f'{self.name} 的健身項(xiàng)目是\'游泳\'')
neo = Persion()
neo.name = 'Neo'
neo.run()
jack = Persion()
jack.top = 180
print('\'Jack\'的身高是', jack.top)
# >>> 執(zhí)行結(jié)果如下
# >>> Neo 的健身項(xiàng)目是'跑步'
# >>> 'Jack'的身高是 180
print('\'Neo\'的身高是', neo.top)
# >>> 執(zhí)行結(jié)果如下:
# >>> AttributeError: 'Persion' object has no attribute 'top'
從上面的 jack.top 與 neo.top 的自定義屬性,我們發(fā)現(xiàn)三件事。
1.實(shí)例化對(duì)象可以自定義屬性
2.每個(gè)實(shí)例化對(duì)象自己定義的屬性與其他實(shí)例化對(duì)象不通用。
3.Persion類(lèi)在實(shí)例化對(duì)象之后,依然只有自己的兩個(gè)屬性 (name 和 age) ,實(shí)例化對(duì)象自定義的屬性僅作用于自己,并不影響 類(lèi) 。
self 的解析與總結(jié)
說(shuō)實(shí)話,關(guān)于 Python 中的 self 我一開(kāi)始接觸的時(shí)候,也是給我搞的云里霧繞、五迷三道的…這里做個(gè)總結(jié),希望對(duì)同樣云里霧繞、五迷三道的童鞋有所幫助。
- Python 中 self 代表的是 類(lèi)的示例 ; self 在定義類(lèi)的方法時(shí)是必須有的,雖然在調(diào)用時(shí)不必傳入相應(yīng)的參數(shù)。
- Python 中 self 只有在針對(duì) 類(lèi) 的情況下,才是有意義的。
- self 只能用在 python 類(lèi) 的方法中。
具體的舉例說(shuō)明如下:
屬性
關(guān)于屬性 - 1:如果變量定義在類(lèi)下面而不是類(lèi)的方法下面,那這個(gè)變量既是類(lèi)的屬性也是類(lèi)實(shí)例的屬性。
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:如果變量定義在類(lèi)的方法下面,如果加了self,那這個(gè)變量就是類(lèi)實(shí)例的屬性,不是類(lèi)的屬性;如果沒(méi)有加self,這個(gè)變量只是這個(gè)方法的局部變量,既不是類(lèi)的屬性也不是類(lèi)實(shí)例的屬性。
class Cat(object):
eyes = '有2只眼睛'
legs = '有4條腿'
tail = '有1只尾巴'
def __init__(self): # 關(guān)于__init__() 會(huì)在下面的 '類(lèi)的構(gòu)造器'有詳細(xì)講解
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:如果在類(lèi)中定義函數(shù)時(shí)加了self,那這個(gè)函數(shù)是類(lèi)實(shí)例的方法,而不是類(lèi)的方法。
class Cat(object):
def eat(self):
print('愛(ài)吃魚(yú)')
dragonLi = Cat()
dragonLi.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> 愛(ài)吃魚(yú)
Cat.cat()
# >>> 執(zhí)行結(jié)果如下:
# >>> TypeError: Cat.eat() missing 1 required positional argument: 'self'
關(guān)于方法2:如果在類(lèi)中定義函數(shù)時(shí)候沒(méi)有加self,那這個(gè)函數(shù)就只是類(lèi)的方法,而不是類(lèi)實(shí)例的方法。
class Cat(object):
def eat():
print('愛(ài)吃魚(yú)')
Cat.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> 愛(ài)吃魚(yú)
dragonLi = Cat()
dragonLi.eat()
# >>> 執(zhí)行結(jié)果如下:
# >>> TypeError: Cat.eat() takes 0 positional arguments but 1 was given
小結(jié)
屬性:
- 如果變量定義在類(lèi)下面而不是類(lèi)的方法下面,那這個(gè)變量既是類(lèi)的屬性也是類(lèi)實(shí)例的屬性。
- 如果變量定義在類(lèi)的方法下面,如果加了self,那這個(gè)變量就是類(lèi)實(shí)例的屬性,不是類(lèi)的屬性;如果沒(méi)有加self,這個(gè)變量只是這個(gè)方法的局部變量,既不是類(lèi)的屬性也不是類(lèi)實(shí)例的屬性。
方法:
- 如果在類(lèi)中定義函數(shù)時(shí)加了self,那這個(gè)函數(shù)是類(lèi)實(shí)例的方法,而不是類(lèi)的方法。
- 如果在類(lèi)中定義函數(shù)時(shí)候沒(méi)有加self,那這個(gè)函數(shù)就只是類(lèi)的方法,而不是類(lèi)實(shí)例的方法。
類(lèi)的構(gòu)造函數(shù)
前面我們了解了 類(lèi)的創(chuàng)建、類(lèi)的屬性、類(lèi)函數(shù)的使用方法,現(xiàn)在我們?cè)賮?lái)看看類(lèi)的構(gòu)造函數(shù)。
什么是類(lèi)的構(gòu)造函數(shù)? —> 構(gòu)造函數(shù)是類(lèi)中的一種默認(rèn)函數(shù),通過(guò)定義它可以在 類(lèi)實(shí)例化 的同時(shí),將參數(shù)傳入類(lèi)中。(類(lèi)似于函數(shù)執(zhí)行的時(shí)候可以傳一些參數(shù))
構(gòu)造函數(shù)的創(chuàng)建方法
重點(diǎn):構(gòu)造函數(shù)依然要在 類(lèi) 中定義
def __init__(self, a, b) # def關(guān)鍵字 + __init__ + 小括號(hào)(括號(hào)內(nèi)第一個(gè)傳入的依然是 self ,后面再跟上希望實(shí)例化時(shí)傳入的參數(shù))
self.a = a # 在構(gòu)造函數(shù)里,將參數(shù)綁定在 self 中,將變量通過(guò) self 綁定之后,就可以在類(lèi)的各個(gè)函數(shù)中進(jìn)行調(diào)用了
self.b = b
構(gòu)造函數(shù)的用法,示例如下:
class Test(object):
def __init__(self, a): # __init__ 構(gòu)造函數(shù)一定要寫(xiě)在第一個(gè),這是一個(gè)很好的編程規(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
接下來(lái)我們?cè)偈褂?構(gòu)造函數(shù) 針對(duì)前面我們創(chuàng)建的 Cat 類(lèi)進(jìn)行修改
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)于對(duì)象的生命周期
注意:這里說(shuō)的對(duì)象的生命周期,指的是實(shí)例化的對(duì)象。
之前我們提到過(guò),當(dāng)一個(gè)變量不使用的時(shí)候就會(huì)被內(nèi)存管家清理掉。 接下來(lái)我們就來(lái)看看一個(gè)變量的一生,從出現(xiàn)到消亡的過(guò)程。之所以在這里插上這一章節(jié)介紹 對(duì)象的生命周期 ,也是為了更好的理解對(duì)象, 從而更好的使用他們。
我們之前學(xué)習(xí)的 深拷貝與淺拷貝, 淺拷貝是創(chuàng)建一個(gè)新的內(nèi)存地址, 而深拷貝是使用之前已經(jīng)定好的變量。
通過(guò)對(duì)一個(gè)對(duì)象的生命周期的理解, 可以讓我們權(quán)衡是終結(jié)一個(gè)對(duì)象還是繼續(xù)使用它們。
我們通過(guò)構(gòu)造函數(shù)完成一個(gè)對(duì)象的實(shí)例化,這個(gè)時(shí)候一個(gè)對(duì)象的生命周期就開(kāi)始了,在這個(gè)時(shí)候內(nèi)存管家發(fā)現(xiàn)有一個(gè)對(duì)象的加入就會(huì)為這個(gè)實(shí)例化的對(duì)象分配一個(gè)內(nèi)存地址(也就是實(shí)例化對(duì)象在內(nèi)存中的家)。
接下里我們就可以操作這個(gè)對(duì)象,可以調(diào)用它的內(nèi)置函數(shù)還有功能。當(dāng)我們不使用這個(gè)對(duì)象的時(shí)候,一般有兩種情況;
第一種是這個(gè)內(nèi)存塊中的值沒(méi)有變量與之綁定了,比如當(dāng)我們的一個(gè)變量的默認(rèn)值被一個(gè)函數(shù)調(diào)用后變量有了新的值,這個(gè)時(shí)候變量原有的默認(rèn)值與變量不再是賦值關(guān)系了。
第二種是當(dāng)我們執(zhí)行完了所有的程序,也就是代碼已經(jīng)執(zhí)行到了最后一行。 Python 解釋器發(fā)現(xiàn)已經(jīng)處理完了所有的業(yè)務(wù),這個(gè)時(shí)候腳本就會(huì)停止處理并釋放腳本中所有的對(duì)象,釋放所有的對(duì)象其實(shí)就是告知內(nèi)存管家,內(nèi)存管家就會(huì)自動(dòng)處理這些對(duì)象的內(nèi)存地址。
以上兩種情況的統(tǒng)一表現(xiàn)形態(tài)都是不再使用這些對(duì)象,這個(gè)時(shí)候每個(gè)對(duì)象中自帶的內(nèi)置函數(shù) __del__ (兩個(gè)下劃線)就會(huì)被調(diào)用,通知內(nèi)存管家從內(nèi)存中釋放每個(gè)對(duì)象對(duì)應(yīng)的內(nèi)存塊。這就是整個(gè)對(duì)象的生命周期。
無(wú)論是字符串、數(shù)字、列表、元組、字典、集合,甚至布爾類(lèi)型與空類(lèi)型,我們知道 Python 中一切皆是對(duì)象,所以它們也是按照這個(gè)規(guī)律存在于消亡。
Python 中的內(nèi)存管理都是自動(dòng)去完成的,所以我們并不需要特意的去對(duì)它進(jìn)行專(zhuān)門(mén)的處理。
關(guān)于 __del__ 函數(shù)并不需要我們書(shū)寫(xiě)和定義,當(dāng)我們實(shí)例化一個(gè)對(duì)象之后,它就會(huì)默認(rèn)存在,并擁有自動(dòng)通知內(nèi)存管家清理內(nèi)存的功能。這也是 Python 的特點(diǎn)之一。
以上就是Python學(xué)習(xí)之面向?qū)ο缶幊淘斀獾脑敿?xì)內(nèi)容,更多關(guān)于Python面向?qū)ο缶幊痰馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python+Pygame實(shí)現(xiàn)之走四棋兒游戲的實(shí)現(xiàn)
大家以前應(yīng)該都聽(tīng)說(shuō)過(guò)一個(gè)游戲:叫做走四棋兒。直接在家里的水泥地上用燒完的炭火灰畫(huà)出幾條線,擺上幾顆石頭子即可。當(dāng)時(shí)的火爆程度可謂是達(dá)到了一個(gè)新的高度。本文將利用Pygame實(shí)現(xiàn)這一游戲,需要的可以參考一下2022-07-07
python有證書(shū)的加密解密實(shí)現(xiàn)方法
這篇文章主要介紹了python有證書(shū)的加密解密實(shí)現(xiàn)方法,采用了M2Crypto組件進(jìn)行相關(guān)的加密解密操作,包含了詳細(xì)的完整實(shí)現(xiàn)過(guò)程,需要的朋友可以參考下2014-11-11
python實(shí)現(xiàn)從wind導(dǎo)入數(shù)據(jù)
今天小編就為大家分享一篇python實(shí)現(xiàn)從wind導(dǎo)入數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
Python從零開(kāi)始創(chuàng)建區(qū)塊鏈
這篇文章主要為大家詳細(xì)介紹了Python從零開(kāi)始創(chuàng)建區(qū)塊鏈的步驟 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
gearman的安裝啟動(dòng)及python API使用實(shí)例
這篇文章主要介紹了gearman的安裝啟動(dòng)及python API使用,需要的朋友可以參考下2014-07-07
淺談python中的getattr函數(shù) hasattr函數(shù)
下面小編就為大家?guī)?lái)一篇淺談python中的getattr函數(shù) hasattr函數(shù)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06
快速排序的算法思想及Python版快速排序的實(shí)現(xiàn)示例
快速排序算法來(lái)源于分治法的思想策略,這里我們將來(lái)為大家簡(jiǎn)單解析一下快速排序的算法思想及Python版快速排序的實(shí)現(xiàn)示例:2016-07-07

