Python中類屬性和實例屬性的區別


在Python中經常會混淆類屬性和實例屬性的概念,今天專門記錄一下個人理解以免日后忘記。

 

看下面的例子:

class Tencent():
    i = 10 # 此處i為類屬性
    def __init__(self,name):
        self.name = name # 此處name為實例屬性
    def function(self):
        print(self.name)

a = Tencent(100) #實例化
print(a.i)
print(a.name)
print(Tencent.i)

運行當然是沒有問題的,輸出結果為:

10
100
10

 

但是當我們加入這樣一段代碼:

print(Tencent.name)

 

運行后會報錯,這是因為不能通過類名+屬性名的方式去調用實例屬性,當類實例化后,只能通過類名去調用方法中的屬性。

 

下面進行這樣的操作:

Tencent.i += 1
print(a.i)print(Tencent.i)

輸出結果為:

11
11

然后再進行:

a.i + = 1
print(a.i)
print(Tencent.i)

輸出結果則為:

11
10

Why?同樣是對類屬性的修改,為什么用不通的調用方式修改后輸出的值卻不一樣呢?

我自己的解釋如下:

當我們使用實例名+屬性名,即a.i的方式修改屬性i的值時:相當於新建了一個i的副本,+1這個操作實際上是進行在這個i的副本上的,而當我們用類名+屬性名的方式調用i時,輸出的其實是原封未動的類屬性i

驗證如下:

 

print(id(a.i)
print(Tencent.i)
a.i += 1 print(a.i,end=" "),print(id(a.i)) #輸出修改后a.i的內存地址 print(Tencent.i,end=" "),print(id(Tencent.i)) #輸出修改后Tencent.i的內存地址

 

輸出結果為:

140712785339504
140712785339504
11 140712785339536
10 140712785339504

結果顯示,修改前后,類屬性i的內存地址其實是沒有變的,通過實例調用修改i其實只是修改了副本。

同理,假如我們直接通過類名的調用方式來修改i,結果為:

print(id(a.i))
print(id(Tencent.i))
Tencent.i += 1
print(a.i,end="  "),print(id(a.i))
print(Tencent.i,end="  "),print(id(Tencent.i))


140712785339504
140712785339504
11  140712785339536
11  140712785339536

可以看到,如果我們直接使用類名+屬性名的方式修改i,那么在修改后i的值確確實實的是變了。

 

總的來說,類和實例對於屬性的修改權限其實就是作用域的問題,類有權限修改屬性,而實例沒有,於是,實例就在自己的內存范圍內創建一個實例名+屬性名的副本,調用的時候就是用的這個。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM