學習面向對象的第一步,就是建立一個類。由於類是面向對象的基石。Python類和其餘編程語言(Java、C#等)的類差很少,也須要使用class關鍵字。下面經過一個實際的例子來看一下Python類是如何建立的。html
本例會建立一個類,以及利用這個類建立兩個對象,並調用其中的方法。編程
1 # 建立一個Person類 2 class Person: 3 # 定義setName方法 4 def setName(self, name): 5 self.name = name 6 # 定義getName方法 7 def getName(self): 8 return self.name 9 # 定義greet方法 10 def greet(self): 11 print("Hello, I'm {name}.".format(name = self.name)) 12 13 # 建立Person對象 14 person1 = Person() 15 # 建立Person對象 16 person2 = Person() 17 # 調用person1對象的setName方法 18 person1.setName("Bill Gates") 19 # 調用person2對象的name屬性 20 person2.name = "Bill Clinton" 21 # 調用person1對象的getName方法 22 print(person1.getName()) 23 # 調用person1對象的greet方法 24 person1.greet() 25 # 調用person2對象的屬性 26 print(person2.name) 27 # 調用person2對象的greet方法,另一種調用方法的方式 28 Person.greet(person2)
程序運行結果以下圖所示。編程語言
從上面的代碼咱們能夠了解到Python類的以下知識點。編輯器
若是使用集成開發環境,如PyDev、PyCharm,那麼代碼編輯器也會對面向對象有很好的支持,例如,當在對象變量後輸入一個點(.)後,IDE會爲咱們列出該對象中全部能夠調用的資源,包括方法和屬性,以下圖所示。函數
Python類默認狀況下,全部的方法均可以被外部訪問。不過像不少其餘編程語言,如Java、C#等,都提供了private關鍵字將方法私有化,也就是說只有類的內部方法才能訪問私有化的方法,經過正常的方式是沒法訪問對象的私有化方法的(除非使用反射技術,這就另當別論了)。不過在Python類中並無提供private或相似的關鍵字將方法私有化,但能夠曲線救國。學習
在Python類的方法名前面加雙下劃線(__)可讓該方法在外部不可訪問。spa
1 class Person: 2 # method1方法在類的外部能夠訪問 3 def method1(self): 4 print("method1") 5 # __method2方法在類的外部不可訪問 6 def __method2(self): 7 print("method2") 8 9 p = Person() 10 p.method1() 11 p.__method2() # 拋出異常
若是執行上面的代碼,會拋出以下圖所示的異常信息,緣由是調用了私有化方法method2。code
其實「method2」方法也不是絕對不可訪問。Python編譯器在編譯Python源代碼時並無將「method2」方法真正私有化,而是一旦遇到方法名以雙下劃線(__)開頭的方法,就會將方法名改爲「ClassNamemethodName」的形式。其中ClassName表示該方法所在的類名,「methodName」表示方法名。ClassName前面要加上但單下劃線()前綴。orm
對於上面的代碼,Python編譯器會將「method2」方法改名爲「_Personmethod2」,因此在類的外部調用「method2」方法會拋出異常。拋出異常的緣由並非「method2」方法被私有化了,而是Python編譯器把「method2」的名稱改成「_Personmethod2」了。當咱們瞭解了這些背後的原理,就能夠經過調用「_Personmethod2」方法來執行「method2」方法。htm
1 p = Person() 2 p._Person__method2() # 正常調用「__method2」方法
本例會建立一個MyClass類,並定義兩個公共的方法(getName和setName)和一個私有的方法(outName)。而後建立了MyClass類的實例,並調用了這些方法。爲了證實Python編譯器在編譯MyClass類時作了手腳,本例還使用了inspect模塊中的getmembers函數獲取MyClass類中全部的成員方法,並輸出方法名。很顯然,「outName」被改爲了「_MyClass__outName」。
1 class MyClass: 2 # 公共方法 3 def getName(self): 4 return self.name 5 # 公共方法 6 def setName(self, name): 7 self.name = name 8 # 在類的內部能夠直接調用私有方法 9 self.__outName() 10 # 私有方法 11 def __outName(self): 12 print("Name = {}".format(self.name)) 13 14 myClass = MyClass() 15 # 導入inspect模塊 16 import inspect 17 # 獲取MyClass類中全部的方法 18 methods = inspect.getmembers(myClass, predicate=inspect.ismethod) 19 print(methods) 20 # 輸出類方法的名稱 21 for method in methods: 22 print(method[0]) 23 print("------------") 24 # 調用setName方法 25 myClass.setName("Bill") 26 # 調用getName方法 27 print(myClass.getName()) 28 # 調用「__outName」方法,這裏調用了改完名後的方法,因此能夠正常執行 29 myClass._MyClass__outName() 30 # 拋出異常,由於「__outName」方法在MyClass類中並不存在 31 print(myClass.__outName())
程序運行結果以下圖所示。
從getmembers函數列出的MyClass類方法的名字能夠看出,「_MyClassoutName」被綁定到了「outName」方法上,咱們能夠將「_MyClassoutName」看作是「outName」的一個別名,一旦爲某個方法起了別名,那麼原來的名字在類外部就不可用了。MyClass類中的getName方法和setName方法的別名和原始方法名相同,因此在外部能夠直接調用getName和setName方法。