一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python面向對象編程之類的進階

Python面向對象編程之類的進階

2022-02-22 12:56一碗周 Python

這篇文章主要介紹了Python面向對象編程之類的引用,引用 Reference是對象的指針,引用是內存中真實對象的指針,表示為變量名或者內存地址、每個對象存在至少一個引用,id()函數用于獲得引用,想具體了解的小伙伴可以參考下面文

1、引用的概念

引用 (Reference)是對象的指針

引用是內存中真實對象的指針,表示為變量名或者內存地址
每個對象存在至少一個引用,id()函數用于獲得引用
在傳遞參數和賦值時,Python傳遞對象的引用,而不是復制對象

示例代碼:

?
1
2
3
4
5
list1 = [1, 2, 3, 4]
list2 = list1
print(id(list1))  # 2044656837192
print(id(list2))  # 2044656837192
# 因為list1是類的實例化,list2引用的是list1,兩個都是引用的最基礎的object類,所以兩個的結果是一樣的

Python內部機制對引用的處理

  • 不可變對象:immutable解釋器為相同值維護盡量少的內存區域
  • 可變對象:mutable解釋器為每個對象維護不同內存區域

示例代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
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

因為text1和2是引用的一個字符串,所以內存地址是一樣的;因為Python解釋器會大可能的節省內存空間,所以當不可變類型的值一樣時,Python會將其自動的引用一個地址空間,來達到節省空間的目的,所以text1/2/3的地址空間是一致的;Python解釋器并不會對計算出來的結果來進行地址空間的優化,就算兩個的值是一樣的,Python解釋器也會為新計算出來的結果來開辟一個新的地址空間

示例代碼:

?
1
2
3
4
5
6
list1 = []
list2 = []
list3 = []
print(id(list1))  # 3204114440776
print(id(list2))  # 3204114440840
print(id(list3))  # 3204115873544

每個可變對象都有自己獨立的地址空間,并不復用地址空間

導致引用被+1的情況一般都4種

  • 對象被創建
  • 對象被引用
  • 對象被作為函數或方法的參數
  • 對象被作為一個容器中的元素

導致引用-1的情況一把也都4種

  • 對象被刪除
  • 對象的名字唄賦予新的對象
  • 對象離開作用域
  • 對象所在容器被刪除

2、對象的拷貝

拷貝是復制一個對象為新對象,內存空間有”變化“,拷貝分為淺拷貝和深拷貝

  • 淺拷貝:僅僅復制最頂層對象的拷貝方式,默認拷貝方式
  • 深拷貝:迭代復制所有對象的拷貝方式

示例代碼(淺拷貝1)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list1 = ["甜甜", [1, 2, 3]]
list2 = list1.copy()  # 使用copy方法復制
list3 = list1[:]  # 使用切片復制
list4 = list(list1)  # 使用生成列表方式復制
for ch in [list1, list2, list3, list4]:
    for i in ch:
        print(i, id(i),  "\t", end="")  # 打印列表的沒一項和id
    print(ch, id(ch))  # 打印每個列表和id
    
'''
---輸出結果---
一碗周 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
'''

淺拷貝只是拷貝的列表這一層的內存空間,里面的元素的內存空間不會被拷貝

示例代碼(淺拷貝2)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list1 = ["一碗周", [1, 2, 3]]
list2 = list1.copy()  # 使用copy方法復制
list3 = list1[:]  # 使用切片復制
list4 = list(list1)  # 使用生成列表方式復制
list4[1].append(4)
print(list1)
print(list2)
print(list3)
print(list4)
'''
--輸出結果--
['一碗周', [1, 2, 3, 4]]
['一碗周', [1, 2, 3, 4]]
['一碗周', [1, 2, 3, 4]]
['一碗周', [1, 2, 3, 4]]
'''

這里只對list4進行來數據的修改,但是所有的列表的內容都發生了;這是因為每個列表所引用的內容是一樣的,所以修改了1個四個會發生改變

深拷貝要采用copy庫里面的deepcopy()方法,迭代拷貝對象內層的各層次對象,完全新開辟內存空間建立對象以及對象下層的各種對象元素,深拷貝僅僅針對可變類別,不可變類型不許創建新對象

示例代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
import copy  # 導入庫
list1 = ["一碗周", [1, 2, 3]]
list2 = copy.deepcopy(list1)  # 使用copy庫的deepcopy方法復制
for ch in [list1, list2]:
    for i in ch:
        print(i, id(i),  "\t", end="")  # 打印列表的沒一項和id
    print(ch, id(ch))  # 打印每個列表和id
 
'''
---輸出結果---
一碗周 2190823984184   [1, 2, 3] 2190853845832   ['一碗周', [1, 2, 3]] 2190853766728
一碗周 2190823984184   [1, 2, 3] 2190853961544   ['一碗周', [1, 2, 3]] 2190853961480
'''

因為“甜甜”字符串屬于不可變類型,所以其地址空間不會發生改變,剩下的地址空間都發生了改變

2.1 實例方法的引用

實例方法也是一種引用,就是對象本身的引用,當方法被引用時,方法(即函數)將產生一個對象:方法對象

2.2 類的特性裝飾器

@property裝飾器可以把方法改變成對外可見的”屬性“,在類內部表現為方法,在外邊表現為屬性

示例代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TestClass:
    def __init__(self, name):
        self.name = name
 
    @property    # 將方法轉換為屬性
    def age(self):
        return self.__age
 
    @age.setter  # 為屬性進行賦值操作
    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)是類中名稱的轉換約定,Python可以通過名稱修飾來完成一些重要功能,在Python中采用下劃線_來進行名稱修飾,分為5種情況,

  • _name
  • name_
  • __name
  • __name__
  • _

3.1 _單下劃線開頭的名稱修飾

  • 單下劃線開頭屬性或者方法為類內部使用的約定,是PEP8規定的一種約定
  • 只是約定,依然可以通過<對象名>.<屬性名>方式訪問
  • 在功能的上的不同是使用from XX import *時不會導入單下劃線開頭的屬性或者方法

示例代碼

?
1
2
3
4
5
6
7
class TestClass:
    def __init__(self, name):
        self._name = name  # 約定在內部使用
 
 
tt = TestClass("一碗周")
print(tt._name)  # 一碗周

雖然約定在內部使用,但是依然可以被訪問

3.2 _單下劃線結尾的名稱修飾

單下劃線結尾的屬性或者方法是避免與保留字或已有命名沖突,這也是PEP8規定的,這僅僅是一個約定,沒有任何對應的功能

3.3 __雙下劃線開頭的名稱修飾

雙下劃線開頭屬性或者方法將被解釋器修改名稱,避免命名沖突,這不是一個約定,而是功能性的, _nama會被修改為_<類名>__name的形式,來實現私有屬性、私有方法;這是一種類的名稱修飾,間接的來當做私有屬性或者私有方法

3.4 __name__雙下劃線開頭和結尾的名稱修飾

雙下劃線開頭和結尾的屬性或方法沒有任何特殊功能,名字不能被修改,部分名稱是保留屬性或者保留方法

3.5 單下劃線

單下劃線僅僅是一個無關緊要的名字嗎,沒有特殊功能

4、Python的最小空類

作用:

類是一個命名空間,最小空類可以當做命名空間使用

  • 最小空類可以輔助存儲和使用
  • 動態增加屬性是Python類的一個特點

示例代碼:

?
1
2
3
4
5
6
7
8
class TestClass:
    pass
 
 
a = TestClass
a.text = "一碗周"
print(a.text)  # 一碗周
# 可以動態增加屬性來達到存儲信息的目的

到此這篇關于Python面向對象編程之類的引用的文章就介紹到這了,更多相關Python類的引用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/7023561803254726669

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产情侣自拍网 | 亚洲AV国产福利精品在现观看 | 四虎影院4hu | 国产haodiaose最新 | 手机免费在线视频 | 精品国产免费 | 波多野结衣黑人系列在线观看 | 996热在线视频 | 国产精品全国探花在线观看 | chinese老头和老太交hd | 午夜福利视频极品国产83 | 国产精品国产三级国产专区不 | 9191久久 | 亚洲天堂视频在线观看免费 | 幻女free性zozo交体内谢 | 亚洲性网 | 日本一区三区 | 91在线精品视频 | 国产欧美日韩视频在线观看一区二区 | ferr孕妇videos毛茸茸 | 黑人女性猛交xxxxxⅹxx | 免费永久视频 | 九九热视频 这里有精品 | 国产成人99久久亚洲综合精品 | 99视频导航 | 男同gay作爰视频网站 | 天天色资料 | 女八把屁股扒开让男生添 | 国产成人性色视频 | 丁香婷婷在线视频 | 99精品观看 | 99视频有精品 | 爽好舒服快想要免费看 | 免费观看在线aa | 91香蕉在线 | 丝袜老师好湿好紧我要进去了 | 翁息肉小说老扒 | 国产露脸对白刺激3p在线 | juliaann大战七个黑人 | 成人在线视频播放 | 给我免费观看的视频在线播放 |