python類變量與構造函數的使用

類變量:可在類的全部實例之間共享的變量
實例類對象:類的實例是調用類對象來建立的。如:par = Parent(),par就是類Parent的一個實例類對象。
實例變量(成員變量):同一個類對象能夠建立多個實例類對象,類定義中有self標誌的變量就是實例變量
 
一個例子,下面的代碼有問題
class MyObject(object): x = 1
    def __init__(self): objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum)
什麼問題呢,看似構造函數__init__中的變量object在實例化對象的時候會自動建立並初始化爲99,其實否則,這裏用一個小的測試代碼就能夠發現問題。
obj = MyObject() obj.showNum() Traceback (most recent call last): File "class.py", line 24, in <module> obj.showNum() File "class.py", line 20, in showNum print("self.num = ", self.objectNum) AttributeError: 'MyObject' object has no attribute 'objectNum'
報錯了,提示實例化對象MyObject並無objectNum這個普通成員變量,爲何呢?
問題就在於,在Python中,類的成員變量必須使用self.propertName進行聲明,這樣才能完成建立,由於self的含義就是表明實例對象;
在這個類中,objectNum和self.objectNum就是兩個徹底不一樣的東西:
定義在__init__函數中的變量objectNum在這裏是一個局部變量,不是類變量
 
接下來咱們能夠再寫一段代碼,調用changNum()方法,來生成這個成員變量self.objectNum:
obj = MyObject() obj.changeNum(10) obj.showNum() >>> self.num =  10
能看到成功返回結果,
因爲在changeNum()方法中,有self.objectNum = anotherNum的賦值,而__init__中,沒有建立類普通成員變量self.objectNum, 而是建立了一個臨時變量objectNum,因此在這裏,雖然changeNum()沒有被自動調用(由於不是__init__()函數),可是其實充當了建立類成員變量和初始化的做用, 可是python並不會在建立新的實例化對象的時候自動調用它。
 
因此經過實驗獲得3個結論:
1.python中的"構造函數"很是的自由,若是不考慮自動調用,任何類方法均可以去建立類成員變量:
class ExampleClass: def createObjectProperty(self, value): self.newObjectProperty = value
如上面的代碼,這裏聲明一個類方法,傳入參數self 和 value,調用這個方法,就能夠生成一個普通成員變量newObjectProperty,並對其賦初值value
2.若是想要找到真正意義上的成員變量,那麼只須要在__init__(self)中聲明self.objectProperty便可
3.python中的self不能隱式調用,若是你不想生成一個臨時變量而是建立一個類成員變量,那麼就應該使用self.variableName
class MyObject(object): x = 1
    def __init__(self): self.objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum)
obj = MyObject()
# obj.changeNum(10)
obj.showNum()
>>>self.num =  99
知道了成員變量的問題以後,再來討論一下類變量
class MyObject(object): x = 1
    def __init__(self): self.objectNum = 99
    def changeNum(self, anotherNum): self.objectNum = anotherNum def showNum(self): print("self.num = ", self.objectNum) obj = MyObject() print(MyObject.x) >>> 1

 

在聲明類T的時候,咱們在全部的方法以外(可是仍在類的做用域中聲明瞭一個變量classNum),從命名的角度來看,咱們但願這是一個類變量,但咱們不但願此次又是一個成員變量,測試發現它確實能夠由類名直接訪問再試一下可否修改:
MyObject.x = 100
print(MyObject.x) >>> 100
發現能夠修改
下面咱們驗證一下其是否能被全部實例化對象訪問和修改,而且是否具備全局性。
t1 = MyObject() print(t1.x) >>> 1 t2 = MyObject() print(t2.x) >>> 1 MyObject.x = 1000
print(t1.x) >>> 1000
print(t2.x) >>> 1000 t1.x = 2000
print(t2.x) >>>1000
print(t1.x) >>>2000
print(MyObject.x) >>>1000
 
從以上結果看出類名.類變量名修改其值會致使實例化對象的值所有被改變,可是用實例化對象名.類變量名修改其值,就僅僅改變本身,不會真的改變類變量的數值。
咱們來檢查一下內存,看一段代碼:
t2 = MyObject() t1 = MyObject() print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>True print(t2.x is t1.x) >>>True --------------------------------------- t2 = MyObject() t1 = MyObject() t2.x = 10
print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>False print(t2.x is t1.x) >>>False -------------------------------------- t2 = MyObject() t1 = MyObject() MyObject.x = 100 t2.x = 10
print(MyObject.x is t1.x) >>>True print(MyObject.x is t2.x) >>>False print(t2.x is t1.x) >>>False
看得出來在最開始的時候MyObject.x和實例化對象t1.x與t2.x內存是同一處的,但當直接修改了實例化對象t2.x的數值後t2.x內存的數值便與其餘兩個不一樣,因此直接修改實例化對象的數值會指向新的內存空間,而且不受類變量改變而改變。
總結:
一個類=類變量(能夠沒有)+構造函數(必須有,沒有的話默認調用)+成員函數(本身定義,能夠沒有)

構造函數中定義了類的成員變量,類的成員變量必定是在構造函數中以self.開頭的變量!python

成員函數中能夠調用成員變量和類變量!成員函數的形參在類的實例調用該函數時傳遞,成員函數的局部變量在該成員函數內部定義。調用成員函數和調用普通函數同樣,只是成員函數由該函數對應的類調用,即須要寫成xxxx.func()而不是直接使用func()!

函數

相關文章
相關標籤/搜索