十四、類變數和實列變數(python)
無論是類屬性還是類方法,都無法像普通變數或者函式那樣,在類的外部直接使用它們。我們可以將類看做一個獨立的空間,則類屬性其實就是在類體中定義的變數,類方法是在類體中定義的函式。
前面章節提到過,在類體中,根據變數定義的位置不同,以及定義的方式不同,類屬性又可細分為以下 3 種型別:
- 類體中、所有函式之外:此範圍定義的變數,稱為類屬性或類變數;
- 類體中,所有函式內部:以“self.變數名”的方式定義的變數,稱為例項屬性或例項變數;
- 類體中,所有函式內部:以“變數名=變數值”的方式定義的變數,稱為區域性變數。
不僅如此,類方法也可細分為例項方法、靜態方法和類方法,後續章節會做詳細介紹。
那麼,類變數、例項變數以及區域性變數之間有哪些不同呢?接下來就圍繞此問題做詳細地講解。
類變數(類屬性)
類變數指的是在類中,但在各個類方法外定義的變數。舉個例子:
class CLanguage :
# 下面定義了2個類變數
name = "C語言中文網"
add = "http://c.biancheng.net"
# 下面定義了一個say例項方法
def say(self, content):
print(content)
上面程式中,name 和 add 就屬於類變數。
類變數的特點是,所有類的例項化物件都同時共享類變數,也就是說,類變數在所有例項化物件中是作為公用資源存在的。類方法的呼叫方式有 2 種,既可以使用類名直接呼叫,也可以使用類的例項化物件呼叫。
比如,在 CLanguage 類的外部,新增如下程式碼:
#使用類名直接呼叫
print(CLanguage.name)
print(CLanguage.add)
#修改類變數的值
CLanguage.name = "Python教程"
CLanguage.add = "http://c.biancheng.net/python"
print(CLanguage.name)
print(CLanguage.add)
程式執行結果為:
C語言中文網
http://c.biancheng.net
Python教程
http://c.biancheng.net/python
可以看到,通過類名不僅可以呼叫類變數,也可以修改它的值。
當然,也可以使用類物件來呼叫所屬類中的類變數(此方式不推薦使用,原因後續會講)。例如,在 CLanguage 類的外部,新增如下程式碼:
clang = CLanguage()
print(clang.name)
print(clang.add)
執行程式,結果為:
C語言中文網
http://c.biancheng.net
注意,因為類變數為所有例項化物件共有,通過類名修改類變數的值,會影響所有的例項化物件。例如,在 CLanguage 類體外部,新增如下程式碼:
print("修改前,各類物件中類變數的值:")
clang1 = CLanguage()
print(clang1.name)
print(clang1.add)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
print("修改後,各類物件中類變數的值:")
CLanguage.name = "Python教程"
CLanguage.add = "http://c.biancheng.net/python"
print(clang1.name)
print(clang1.add)
print(clang2.name)
print(clang2.add)
程式執行結果為:
修改前,各類物件中類變數的值:
C語言中文網
http://c.biancheng.net
C語言中文網
http://c.biancheng.net
修改後,各類物件中類變數的值:
Python教程
http://c.biancheng.net/python
Python教程
http://c.biancheng.net/python
顯然,通過類名修改類變數,會作用到所有的例項化物件(例如這裡的 clang1 和 clang2)。
注意,通過類物件是無法修改類變數的。通過類物件對類變數賦值,其本質將不再是修改類變數的值,而是在給該物件定義新的例項變數(在講例項變數時會進行詳細介紹)。
值得一提的是,除了可以通過類名訪問類變數之外,還可以動態地為類和物件新增類變數。例如,在 CLanguage 類的基礎上,新增以下程式碼:
clang = CLanguage()
CLanguage.catalog = 13
print(clang.catalog)
執行結果為:
13
例項變數(例項屬性)
例項變數指的是在任意類方法內部,以“self.變數名”的方式定義的變數,其特點是隻作用於呼叫方法的物件。另外,例項變數只能通過物件名訪問,無法通過類名訪問。
舉個例子:
class CLanguage :
def __init__(self):
self.name = "C語言中文網"
self.add = "http://c.biancheng.net"
# 下面定義了一個say例項方法
def say(self):
self.catalog = 13
此 CLanguage 類中,name、add 以及 catalog 都是例項變數。其中,由於 init() 函式在建立類物件時會自動呼叫,而 say() 方法需要類物件手動呼叫。因此,CLanguage 類的類物件都會包含 name 和 add 例項變數,而只有呼叫了 say() 方法的類物件,才包含 catalog 例項變數。
例如,在上面程式碼的基礎上,新增如下語句:
clang = CLanguage()
print(clang.name)
print(clang.add)
#由於 clang 物件未呼叫 say() 方法,因此其沒有 catalog 變數,下面這行程式碼會報錯
#print(clang.catalog)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
#只有呼叫 say(),才會擁有 catalog 例項變數
clang2.say()
print(clang2.catalog)
執行結果為:
C語言中文網
http://c.biancheng.net
C語言中文網
http://c.biancheng.net
13
前面講過,通過類物件可以訪問類變數,但無法修改類變數的值。這是因為,通過類物件修改類變數的值,不是在給“類變數賦值”,而是定義新的例項變數。例如,在 CLanguage 類體外,新增如下程式:
clang = CLanguage()
#clang訪問類變數
print(clang.name)
print(clang.add)
clang.name = "Python教程"
clang.add = "http://c.biancheng.net/python"
#clang例項變數的值
print(clang.name)
print(clang.add)
#類變數的值
print(CLanguage.name)
print(CLanguage.add)
程式執行結果為:
C語言中文網
http://c.biancheng.net
Python教程
http://c.biancheng.net/python
C語言中文網
http://c.biancheng.net
顯然,通過類物件是無法修改類變數的值的,本質其實是給 clang 物件新新增 name 和 add 這 2 個例項變數。
類中,例項變數和類變數可以同名,但這種情況下使用類物件將無法呼叫類變數,它會首選例項變數,這也是不推薦“類變數使用物件名呼叫”的原因。
另外,和類變數不同,通過某個物件修改例項變數的值,不會影響類的其它例項化物件,更不會影響同名的類變數。例如:
class CLanguage :
name = "xxx" #類變數
add = "http://" #類變數
def __init__(self):
self.name = "C語言中文網" #例項變數
self.add = "http://c.biancheng.net" #例項變數
# 下面定義了一個say例項方法
def say(self):
self.catalog = 13 #例項變數
clang = CLanguage()
#修改 clang 物件的例項變數
clang.name = "python教程"
clang.add = "http://c.biancheng.net/python"
print(clang.name)
print(clang.add)
clang2 = CLanguage()
print(clang2.name)
print(clang2.add)
#輸出類變數的值
print(CLanguage.name)
print(CLanguage.add)
程式執行結果為:
python教程
http://c.biancheng.net/python
C語言中文網
http://c.biancheng.net
xxx
http://
不僅如此,Python 只支援為特定的物件新增例項變數。例如,在之前程式碼的基礎上,為 clang 物件新增 money 例項變數,實現程式碼為:
clang.money = 30
print(clang.money)
區域性變數
除了例項變數,類方法中還可以定義區域性變數。和前者不同,區域性變數直接以“變數名=值”的方式進行定義,例如:
class CLanguage :
# 下面定義了一個say例項方法
def count(self,money):
sale = 0.8*money
print("優惠後的價格為:",sale)
clang = CLanguage()
clang.count(100)
通常情況下,定義區域性變數是為了所在類方法功能的實現。需要注意的一點是,區域性變數只能用於所在函式中,函式執行完成後,區域性變數也會被銷燬。
相關文章
- python整數和變數Python變數
- python變數和引數Python變數
- 變數的分類(臨時(本地)變數、環境變數、全域性變數和系統變數)變數
- Python中類變數、成員變數、區域性變數的區別Python變數
- 成員變數、全域性變數、例項變數、類變數、靜態變數和區域性變數的區別變數
- Java - 24 類變數和類方法Java變數
- python變數與變數作用域Python變數
- Python中的全域性變數和區域性變數Python變數
- Python變數Python變數
- Python - 變數Python變數
- java類變數Java變數
- 類,物件,成員變數和區域性變數,匿名物件物件變數
- Java中變數之區域性變數、本類成員變數、父類成員變數的訪問方法Java變數
- Java 變數種類Java變數
- Python - 物件導向程式設計 - 類變數、例項變數/類屬性、例項屬性Python物件程式設計變數
- Python 函式和變數作用域Python函式變數
- Python可變引數*args和**kwargsPython
- python—資料型別和變數Python資料型別變數
- 成員變數和區域性變數變數
- 區域性變數和全域性變數變數
- 介面測試實戰--postman全域性變數和環境變數Postman變數
- Bash變數和引數變數
- Java訪問類變數Java變數
- Python學習-變數Python變數
- Python基礎:變數Python變數
- python變數基礎Python變數
- java 全域性變數和區域性變數Java變數
- jmeter全域性變數和區域性變數JMeter變數
- Spark 外部變數和BroadCast變數的區別Spark變數AST
- Python學習之變數、物件和引用Python變數物件
- Python中私有變數和私有方法Python變數
- Python閉包和儲存自由變數Python變數
- Python 中的閉包和自由變數Python變數
- Python檢視模組(變數、函式、類)方法Python變數函式
- Shell程式設計-shell變數2-位置變數和預定義變數程式設計變數
- python---函式引數、變數Python函式變數
- Go語言變數生命期和變數逃逸分析Go變數
- systemtap 探祕(三)- 型別、變數和陣列型別變數陣列