Python面向?qū)ο缶幊讨惖倪M(jìn)階
1、引用的概念
引用 (Reference)是對(duì)象的指針
引用是內(nèi)存中真實(shí)對(duì)象的指針,表示為變量名或者內(nèi)存地址
每個(gè)對(duì)象存在至少一個(gè)引用,id()函數(shù)用于獲得引用
在傳遞參數(shù)和賦值時(shí),Python傳遞對(duì)象的引用,而不是復(fù)制對(duì)象
示例代碼:
list1 = [1, 2, 3, 4] list2 = list1 print(id(list1)) # 2044656837192 print(id(list2)) # 2044656837192 # 因?yàn)閘ist1是類的實(shí)例化,list2引用的是list1,兩個(gè)都是引用的最基礎(chǔ)的object類,所以兩個(gè)的結(jié)果是一樣的
Python內(nèi)部機(jī)制對(duì)引用的處理
- 不可變對(duì)象:
immutable解釋器為相同值維護(hù)盡量少的內(nèi)存區(qū)域 - 可變對(duì)象:
mutable解釋器為每個(gè)對(duì)象維護(hù)不同內(nèi)存區(qū)域
示例代碼:
text1 = "一碗周" text2 = text1 text3 = "一碗周" text4 = "一碗" text5 = "周" text6 = text4 + text5 print(id(text1)) # 1616972638288 print(id(text2)) # 1616972638288 print(id(text3)) # 1616972638288 print(id(text4)) # 1616973621272 print(id(text5)) # 1616973578032 print(id(text6)) # 1616974246288
因?yàn)?code>text1和2是引用的一個(gè)字符串,所以內(nèi)存地址是一樣的;因?yàn)?code>Python解釋器會(huì)大可能的節(jié)省內(nèi)存空間,所以當(dāng)不可變類型的值一樣時(shí),Python會(huì)將其自動(dòng)的引用一個(gè)地址空間,來(lái)達(dá)到節(jié)省空間的目的,所以text1/2/3的地址空間是一致的;Python解釋器并不會(huì)對(duì)計(jì)算出來(lái)的結(jié)果來(lái)進(jìn)行地址空間的優(yōu)化,就算兩個(gè)的值是一樣的,Python解釋器也會(huì)為新計(jì)算出來(lái)的結(jié)果來(lái)開(kāi)辟一個(gè)新的地址空間
示例代碼:
list1 = [] list2 = [] list3 = [] print(id(list1)) # 3204114440776 print(id(list2)) # 3204114440840 print(id(list3)) # 3204115873544
每個(gè)可變對(duì)象都有自己獨(dú)立的地址空間,并不復(fù)用地址空間
導(dǎo)致引用被+1的情況一般都4種
- 對(duì)象被創(chuàng)建
- 對(duì)象被引用
- 對(duì)象被作為函數(shù)或方法的參數(shù)
- 對(duì)象被作為一個(gè)容器中的元素
導(dǎo)致引用-1的情況一把也都4種
- 對(duì)象被刪除
- 對(duì)象的名字唄賦予新的對(duì)象
- 對(duì)象離開(kāi)作用域
- 對(duì)象所在容器被刪除
2、對(duì)象的拷貝
拷貝是復(fù)制一個(gè)對(duì)象為新對(duì)象,內(nèi)存空間有”變化“,拷貝分為淺拷貝和深拷貝
- 淺拷貝:僅僅復(fù)制最頂層對(duì)象的拷貝方式,默認(rèn)拷貝方式
- 深拷貝:迭代復(fù)制所有對(duì)象的拷貝方式
示例代碼(淺拷貝1)
list1 = ["甜甜", [1, 2, 3]]
list2 = list1.copy() # 使用copy方法復(fù)制
list3 = list1[:] # 使用切片復(fù)制
list4 = list(list1) # 使用生成列表方式復(fù)制
for ch in [list1, list2, list3, list4]:
for i in ch:
print(i, id(i), "\t", end="") # 打印列表的沒(méi)一項(xiàng)和id
print(ch, id(ch)) # 打印每個(gè)列表和id
'''
---輸出結(jié)果---
一碗周 2905817180184 [1, 2, 3] 2905787490888 ['一碗周', [1, 2, 3]] 2905787490952
一碗周 2905817180184 [1, 2, 3] 2905787490888 ['一碗周', [1, 2, 3]] 2905817092488
一碗周 2905817180184 [1, 2, 3] 2905787490888 ['一碗周', [1, 2, 3]] 2905817137800
一碗周 2905817180184 [1, 2, 3] 2905787490888 ['一碗周', [1, 2, 3]] 2905817771656
'''
淺拷貝只是拷貝的列表這一層的內(nèi)存空間,里面的元素的內(nèi)存空間不會(huì)被拷貝
示例代碼(淺拷貝2)
list1 = ["一碗周", [1, 2, 3]] list2 = list1.copy() # 使用copy方法復(fù)制 list3 = list1[:] # 使用切片復(fù)制 list4 = list(list1) # 使用生成列表方式復(fù)制 list4[1].append(4) print(list1) print(list2) print(list3) print(list4) ''' --輸出結(jié)果-- ['一碗周', [1, 2, 3, 4]] ['一碗周', [1, 2, 3, 4]] ['一碗周', [1, 2, 3, 4]] ['一碗周', [1, 2, 3, 4]] '''
這里只對(duì)list4進(jìn)行來(lái)數(shù)據(jù)的修改,但是所有的列表的內(nèi)容都發(fā)生了;這是因?yàn)槊總€(gè)列表所引用的內(nèi)容是一樣的,所以修改了1個(gè)四個(gè)會(huì)發(fā)生改變
深拷貝要采用copy庫(kù)里面的deepcopy()方法,迭代拷貝對(duì)象內(nèi)層的各層次對(duì)象,完全新開(kāi)辟內(nèi)存空間建立對(duì)象以及對(duì)象下層的各種對(duì)象元素,深拷貝僅僅針對(duì)可變類別,不可變類型不許創(chuàng)建新對(duì)象
示例代碼
import copy # 導(dǎo)入庫(kù)
list1 = ["一碗周", [1, 2, 3]]
list2 = copy.deepcopy(list1) # 使用copy庫(kù)的deepcopy方法復(fù)制
for ch in [list1, list2]:
for i in ch:
print(i, id(i), "\t", end="") # 打印列表的沒(méi)一項(xiàng)和id
print(ch, id(ch)) # 打印每個(gè)列表和id
'''
---輸出結(jié)果---
一碗周 2190823984184 [1, 2, 3] 2190853845832 ['一碗周', [1, 2, 3]] 2190853766728
一碗周 2190823984184 [1, 2, 3] 2190853961544 ['一碗周', [1, 2, 3]] 2190853961480
'''
因?yàn)椤疤鹛稹弊址畬儆诓豢勺冾愋停云涞刂房臻g不會(huì)發(fā)生改變,剩下的地址空間都發(fā)生了改變
2.1 實(shí)例方法的引用
實(shí)例方法也是一種引用,就是對(duì)象本身的引用,當(dāng)方法被引用時(shí),方法(即函數(shù))將產(chǎn)生一個(gè)對(duì)象:方法對(duì)象
2.2 類的特性裝飾器
@property裝飾器可以把方法改變成對(duì)外可見(jiàn)的”屬性“,在類內(nèi)部表現(xiàn)為方法,在外邊表現(xiàn)為屬性
示例代碼
class TestClass:
def __init__(self, name):
self.name = name
@property # 將方法轉(zhuǎn)換為屬性
def age(self):
return self.__age
@age.setter # 為屬性進(jìn)行賦值操作
def age(self, value):
if value < 0 or value > 110:
value = 19
self.__age = value
tt = TestClass("一碗周")
bb = TestClass("一碗粥")
tt.age = 18
bb.age = -19
print(tt.age) # 18
print(bb.age) # 19
3、類的名稱修飾
名稱修飾 (Name Mangling)是類中名稱的轉(zhuǎn)換約定,Python可以通過(guò)名稱修飾來(lái)完成一些重要功能,在Python中采用下劃線_來(lái)進(jìn)行名稱修飾,分為5種情況,
_name
name_
__name
__name__
_
3.1 _單下劃線開(kāi)頭的名稱修飾
- 單下劃線開(kāi)頭屬性或者方法為類內(nèi)部使用的約定,是
PEP8規(guī)定的一種約定 - 只是約定,依然可以通過(guò)<對(duì)象名>.<屬性名>方式訪問(wèn)
- 在功能的上的不同是使用
from XX import*時(shí)不會(huì)導(dǎo)入單下劃線開(kāi)頭的屬性或者方法
示例代碼
class TestClass:
def __init__(self, name):
self._name = name # 約定在內(nèi)部使用
tt = TestClass("一碗周")
print(tt._name) # 一碗周
雖然約定在內(nèi)部使用,但是依然可以被訪問(wèn)
3.2 _單下劃線結(jié)尾的名稱修飾
單下劃線結(jié)尾的屬性或者方法是避免與保留字或已有命名沖突,這也是PEP8規(guī)定的,這僅僅是一個(gè)約定,沒(méi)有任何對(duì)應(yīng)的功能
3.3 __雙下劃線開(kāi)頭的名稱修飾
雙下劃線開(kāi)頭屬性或者方法將被解釋器修改名稱,避免命名沖突,這不是一個(gè)約定,而是功能性的, _nama會(huì)被修改為_(kāi)<類名>__name的形式,來(lái)實(shí)現(xiàn)私有屬性、私有方法;這是一種類的名稱修飾,間接的來(lái)當(dāng)做私有屬性或者私有方法
3.4 __name__雙下劃線開(kāi)頭和結(jié)尾的名稱修飾
雙下劃線開(kāi)頭和結(jié)尾的屬性或方法沒(méi)有任何特殊功能,名字不能被修改,部分名稱是保留屬性或者保留方法
3.5 單下劃線
單下劃線僅僅是一個(gè)無(wú)關(guān)緊要的名字嗎,沒(méi)有特殊功能
4、Python的最小空類
作用:
類是一個(gè)命名空間,最小空類可以當(dāng)做命名空間使用
- 最小空類可以輔助存儲(chǔ)和使用
- 動(dòng)態(tài)增加屬性是
Python類的一個(gè)特點(diǎn)
示例代碼:
class TestClass:
pass
a = TestClass
a.text = "一碗周"
print(a.text) # 一碗周
# 可以動(dòng)態(tài)增加屬性來(lái)達(dá)到存儲(chǔ)信息的目的
到此這篇關(guān)于Python面向?qū)ο缶幊讨惖囊玫奈恼戮徒榻B到這了,更多相關(guān)Python類的引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Selenium+Webdriver 常用的元素定位方式
這篇文章主要介紹了淺談Selenium+Webdriver 常用的元素定位方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
python自動(dòng)化測(cè)試中裝飾器@ddt與@data源碼深入解析
最近工作中接觸了python自動(dòng)化測(cè)試,所以下面這篇文章主要給大家介紹了關(guān)于python自動(dòng)化測(cè)試中裝飾器@ddt與@data源碼解析的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Pycharm中無(wú)法使用pip安裝的包問(wèn)題解決方案
本文主要介紹了Pycharm中無(wú)法使用pip安裝的包問(wèn)題解決方案,在終端通過(guò)pip裝好包以后,在pycharm中導(dǎo)入包時(shí),依然會(huì)報(bào)錯(cuò),下面就來(lái)介紹一下解決方法2023-09-09
Python實(shí)現(xiàn)自動(dòng)駕駛訓(xùn)練模型
這篇文章主要為大家介紹了Python實(shí)現(xiàn)自動(dòng)駕駛訓(xùn)練模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Python技巧匿名函數(shù)、回調(diào)函數(shù)和高階函數(shù)
本文分享的是Python技巧匿名函數(shù)、回調(diào)函數(shù)和高階函數(shù),我們?cè)赑ython中使用lambda表達(dá)式來(lái)使用匿名函數(shù),回調(diào)函數(shù)即callback,先寫(xiě)一個(gè)函數(shù),讓預(yù)先寫(xiě)好的系統(tǒng)來(lái)調(diào)用,一個(gè)函數(shù)可以作為參數(shù)傳給另外一個(gè)函數(shù),或者一個(gè)函數(shù)的返回值為另外一個(gè)函數(shù),滿足其一則為高階函數(shù)2021-12-12
Django表單外鍵選項(xiàng)初始化的問(wèn)題及解決方法
這篇文章主要介紹了Django表單外鍵選項(xiàng)初始化的問(wèn)題及解決方法,需本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,要的朋友可以參考下2021-04-04

