類中的方法,其實就是類中的函數,可以分為:實例方法,類方法,靜態方法。方法和字段一樣,也是屬於類的屬性,所以也具有運行中修改的特效, 但一般不推薦這樣做。
我在類的基本語法中,介紹了構造器方法:__init__ 、__new__;解構器方法:__del__;
注意,這里雖然是以兩個下划線(__)開頭,但同時以兩個下划線(__)結尾,這里表明其是一個‘魔法方法’,關於類中的魔法方法,將起一篇進行說明。
但是,如果單純只以兩個下划線開始,則依然是私有化的意思,看代碼示例:
class Test(object): def __scolia__(self): # 一個類似魔術方法,並不是私有化 return 'scolia' def __good(self): # 私有方法 return 'good' a = Test() print a.__scolia__() # 魔法方法可以在直接訪問 print a.__good() # 私有方法不能直接訪問

同樣的,和字段私有化一樣,我們也可能同特殊手段進行強制訪問:
print a._Test__good() # 強制訪問

當然,私有方法也可以在類的內部訪問,和私有字段一樣。
所以說,屬性的私有化都是對訪問入口進行混淆,同樣的,也不建議強制訪問私有屬性。
也許這里的‘魔法方法’看起來並不‘魔法’,詳情將以后解釋。
實例方法:
在 __init__ 構造器中,提起過其是一個實例方法,實例方法的特點就是:
1.方法的第一個參數必須是 self,當然這是約定俗成的寫法,你可以將 self 換成 abc 之類的,但是為了別的程序員能看得懂,還是統一用 self 吧。這里的 self 代表實例本身,也就是說如果我實例化時使用的是: a = Test() ,那么 self 就代表 a 這個實例,我們可以在很多構造器中看到類似 self.scolia = 'good' 的寫法,其實這個寫法和在類外面 a.scolia = 'good' 效果一樣,是為了添加屬性,只不過 __init__ 方法是實例化時自動調用的函數,所以適合進行初始屬性的創建。
2.實例方法在調用的時候,self 是自動傳遞的,所以不需要我們再處理。
3.實例方法一般要有實例才能調用,當然也有特殊的調用方法。
代碼示例:
class Test(object): def __init__(self, a, b): # 構造器在實例創建時進行屬性的初始化 self.a = int(a) self.b = int(b) def abc(self, c): # 實例方法 print self.a + self.b + int(c) # 因為self是自動傳遞的,所以我們可以在實例方法中調用實例的屬性 a = Test(123, 321) # 我們只要為 a 和 b 傳參就行了 a.abc(666) # 同樣的,只要為 c 傳參

這里,將引入一個綁定 (binding) 的概念,其主要和方法的調用有關。
首先,我們知道方法是類的屬性,而不是實例的屬性,在上篇博文類的屬性和實例的屬性中我們也討論過這個問題。
其次,方法只有在其所屬的類擁有實例時,才能被調用。當一個類存在實例后,方法才被認為是綁定到這個實例。沒有實例的時候,方法是未綁定的。
最后,任何一個方法定義的第一個參數都是變量 self ,它表示調用此方法的實例對象。
很明顯這里的綁定針對的是實例方法。因為如果沒有實例的話,self 就無法傳遞,這將導致參數的不足,當然就無法調用了。
但是,我們可以自己傳遞 self 來調用未綁定的方法。調用未綁定的方法通常是在我們繼承了一個父類后, 我們覆蓋了父類中的某個方法,但是為了實現代碼重用,我們又想在子類中調用父類的方法。單純的復制父類中的代碼明顯不是一個好選擇, 除了浪費系統資源之外,還有可能在復制的時候出錯,而且以后修改父類的代碼之后,還要修改相應子類中的代碼,實在太低效,這個時候就是調用未綁定方法的場景。
代碼示例:
class abc(object): def __init__(self, a): self.a = -int(a) class Test(abc): def __init__(self, a, b): abc.__init__(self, a) # 調用父類的構造器,並手動傳遞 self self.b = b def fangfa(self): print self.a + self.b # 屬性 a 由父類的構造器創建,b 由子類構造器創建 a = Test(123, 321) # 我們只創建了子類的實例,而沒有創建父類的實例 a.fangfa()

本來我們沒有創建父類的示例,是無法調用父類的實例方法的,但是我們手動傳遞了實例方法需要的 self 參數,就可以實現調用了。
這里的順序是,我們創建了 Test 的實例,其 self 是自動傳遞的,故 Test 的構造方法 __init__(self, a, b) 中 self 就代表實例 a,而我們又調用了父類的 abc.__init__(self, a) 這里的 self 就是子類的實例 a ,參數 a 就是我們傳的 123,而父類中 self.a = -int(a) ;最后我們可在子類的方法中調用 self.a 這個屬性。
類方法:
類方法其實和實例方法類似,不過其第一個參數一般是 cls (約定俗成)而不是 self。但是,如果我們直接將 self 換成 cls 來創建類方法是不對的,因為實例方法的首個參數也是任意的,只是統一使用 self 。python的解釋器並沒有說看見第一個參數是 cls 就知道這個是類方法,它還是將其當作是實例方法來對待,所以我們需要通過內建函數: classmethod() 來創建類方法。
代碼示例:
class Test(object): def abc(cls): print cls.__name__ # 打印類名 abc = classmethod(abc) # 通過普通的函數傳參的方式創建類方法 a = Test() Test.abc() # 類能調用 a.abc() # 實例也能調用

當然,有同學在看到這段代碼的時候想到了裝飾器,實際上我們也可以使用裝飾器的方法來創建類方法:
class Test(object): @classmethod def abc(cls): print cls.__name__ # 打印類名
結果也是一樣的,具體選擇看個人喜好。
注意,因為使用了 classmethod()函數,其第一個參數 cls 是固定傳遞的,而且是代表當前的類。並沒有實例方法中非綁定方法的調用形式。
靜態方法:
靜態方法其實就是類中的一個普通函數,它並沒有默認傳遞的參數,在創建靜態方法的時候,需要用到內置函數: staticmethod() 。
代碼示例:
class Test(object): def abc(): print 'abc' abc = staticmethod(abc) @staticmethod def xyz(a, b): print a + b Test.abc() # 類調用 Test.xyz(1, 2) # 類調用 a = Test() a.abc() # 實例調用 a.xyz(3, 4) # 實例調用

注意,雖然靜態方法沒有默認參數, 但並不代表不能有參數。
總結:
1.實例方法需要至少一個默認參數 self。
2.類方法需要至少一個默認參數 cls。
3.靜態方法不需要默認參數。
另外:方法也是屬性,所以在類的內部,我們可通過 self.abc()、cls.abc() 的方式來調用類中的其他方法,當然要注意傳參的問題。
用方法冒充字段:
有時候,我們的一個方法在經過一系列處理以后,返回的是一個數據,例如:
class Test: def __init__(self, a, b): self.a = a self.b = b def fangfa(self): c = self.a + self.b return c # 返回處理的結果數據 a = Test(1, 2) b = a.fangfa() # 調用方法,得到返回值 print b

但是,懶惰的程序員們想:我想要的只是和字段類似的數據,卻要調用一個方法,有時候容易搞錯,能不能用字段的形式獲取數據呢?這樣更加符合直覺。
可以,只有使用 property() 函數就可以了。同樣的,這里也有兩種創建方式,這里只演示裝飾器的方式:
class Test: def __init__(self, a, b): self.a = a self.b = b @property def fangfa(self): c = self.a + self.b return c a = Test(1, 2) b = a.fangfa # 不用帶括號了 print b
這樣是實現了方法偽裝成字段了。其實就是懶惰的程序員們不願意多寫一個括號,當然還有一些其他好處。
另外,函數要用返回值,不然就默認為 None 了。
如果在經典類中,我們就只能做到這樣了。
但是,使用新式類的話,就能有更多的功能:
class Test(object): def __init__(self, a, b): self.a = a self.b = b @property def fangfa(self): c = self.a + self.b return c @fangfa.setter def fangfa(self, value): self.a = value @fangfa.deleter def fangfa(self): print '屬性已刪除' a = Test(1, 2) b = a.fangfa # 獲得方法的返回值 print b a.fangfa = 100 # 執行 fangfa.setter 修飾的方法,並讓value = 100 print a.a del a.fangfa # 執行 fangfa.deleter 修飾的方法

注意后面兩個裝飾器的名字。
另外,方法必須要先經過 property()函數的裝飾后,才有后面兩個裝飾器的用法。
如果使用非裝飾器的形式的話:
class Test(object): def __init__(self, a, b): self.a = a self.b = b def fangfa_get(self): c = self.a + self.b return c def fangfa_set(self, value): self.a = value def fangfa_del(self): print '屬性已刪除' fangfa = property(fangfa_get, fangfa_set, fangfa_del)
property(fget=None, fset=None, fdel=None, doc=None)
最后的 doc 是說明文檔,看個人需要添加,可通過 Test.fangfa.__doc__ 進行訪問。
關於方法就先說這么多,以后有需要再進行修改補充。
