1:定義一個類
首先在python中,定義一個類,作爲例子,然後引出相關知識點
class Example(object):
def __init__(self,data1,data2):
self.__data1=data1
self.data2=data2
def __func1(self):
print("Example類的私有方法可以被調用!")
def show_data(self):
self.__func1()
print(self.__data1)
print(self.data2)
exp= Example(50,100)
exp.show_data()
輸出結果:
Example類的私有方法可以被調用!
50
100
這裏,__init__是定義的類的構造函數,可以對類的變量進行初始化,只要類被實例化的時候,就會先執行構造函數。
2:類的實例
類的實例化很簡單,只要根據類的初始屬性是否爲空的情況決定。
比如1--類的初始狀態爲空:
class Example(object):
def __init__(self):
print("Example類的私有方法可以被調用!")
exp=Example()
輸出結果:
Example類的私有方法可以被調用!
再比如2:類的初始狀態不爲空,需要傳入屬性:
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
exp=Example(10,20)
exp.data1
輸出結果:
10
3:類的封裝
在python中,類的封裝有兩層含義,一種是對數據的封裝 ,一種是對實現邏輯方法的封裝
比如1:對數據的封裝
還是剛剛上面的那個例子:
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
exp=Example(10,20)
exp.data1
在這個示例中,對象exp經過Example實例化後,就具有兩個屬性,即data1和data2,所以data1和data2就是對數據的封裝。
再比如2:對邏輯的封裝(對輸入的兩個數求和):
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
def add(self):
print(self.data1+self.data2)
exp=Example(10,20)
exp.add()
輸出結果:
30
上面的實例中,add函數實現了對兩個數求和的功能,但是這個功能的實現,在類的外部是看不到這個過程的,當類被實例化後,類的對象調用這個函數時,會輸出結果。這就是實現邏輯的封裝。
4:繼承
繼承是面向對象編程的重要組成部分。以下是一個簡單實例。
class Father(object):
def __init__(self, age):
self.age=age
print ( "age: %d" %( self.age) )
def getAge(self):
return self.age
class Son(Father):
def __init__(self, age):
print ( "hello world" )
self.age = age
son=Son(18)
print (son.getAge())
輸出結果:
hello world
18
這裏,子類Son繼承父類Father,因此子類可以使用父類所有公開方法,不需要再創建,比如這裏子類直接調用父類的getAge方法。
此外,關於繼承中的靜態方法,類方法等知識,可以參考Python-實例方法靜態方法類方法對比總結(附Python代碼)
5:類的私有屬性
關於類的私有屬性和私有方法,相對上述內容來說,要抽象一點。
Python 沒有像C++,java那樣明確的共有,私有,受保護的關鍵字來描述成員方法或屬性,在Python中,它使用既定的單下劃線"_"和雙下劃線"__"作爲私有函數或屬性的標識。這裏使用單下劃線還是雙下劃線有很大區別。
- 單下劃線的函數或屬性,在類的定義中可以調用和訪問,類的實例也可以直接訪問,子類也可以訪問;
- 雙下劃線的函數或屬性,在類的定義中可以調用和訪問,類的實例不可以直接訪問,子類不可以訪問。
實例:
class Father():
def __private(self):
print("父類的私有函數private")
def _protected(self):
print("父類的受保護函數protected")
def public(self):
print("父類的公有函數public")
self.__private()
self._protected()
class Son(Father):
def __private(self):
print("子類的重載私有函數private")
def _protected(self):
print("子類的重載受保護protected")
s = Son()
s.public()
輸出結果:
父類的公有函數public
父類的私有函數private
子類的重載受保護protected
上面的例子中,父類的public是共有函數,可以被子類直接調用,__private是父類的私有方法,不可以在類外調用,但是可以通過類內的public方法調用__private,即使私有方法可以在類的內部被調用。
繼續上面的例子,我們重新輸入:
s = Son()
# s.public()
s._protected()
輸出結果:
子類的重載受保護protected
從結果中,我們發現子類的單下劃線方法_protected覆蓋了父類的_protected方法,但是上面的例子中是輸出的是父類Father的私有函數__private,也就意味着子類沒有覆蓋父類的__private方法,即:父類的雙下劃線__private只能被自身訪問。那麼如何子類如何調用自身的__private函數呢?
我們重新輸入:
s = Son()
# s.public()
# s._protected()
s._Son__private()
輸出結果:
子類的重載私有函數private
結果正是我們想要的:子類Son輸出的是自身的__private函數。
對比兩個結果說明:子類雙劃線方法__private方法並沒有覆蓋父類雙下劃線__private方法的權限,但是子類的單下劃線方法_protected方法是可以覆蓋父類的單下劃線_protected方法
繼續追問,既然子類普通函數和單下劃線函數都可以覆蓋父類的普通函數和單下劃線函數,那麼普通函數和單下劃線受保護函數之間有什麼區別呢?
其實,在同一個py腳本下看不出區別,但是如果py作爲模塊導入的時候,單下劃線不能導入到模塊,即:_protected 不能用於’from module import *’ 以單下劃線開頭的表示的是protected類型的變量。即受保護類型只能允許其本身與子類進行訪問。
接着我們重新看剛剛上面輸入的s._Son__private(),爲什麼實例後面要跟上一個單下劃線和一個類名呢?
實際上,Python使用名字混淆的方法,將雙下劃線私有方法"__method"編程了"_claseename__method"了。
所以不要在一個類中同時使用__method和 _ClassName__method
例如,下面這樣的程序就會報錯
class example():
def _protected(self):
print("example 保護函數")
def __private(self):
print("正常 私有函數")
def _example__private(self):
print("特殊 _example__private")
def public(self):
print(" 共有函數")
self.__hide()
example().public()
報錯的輸出結果:
共有函數
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-54-0e9ff18afbe4> in <module>()
13 self.__hide()
14
---> 15 example().public()
<ipython-input-54-0e9ff18afbe4> in public(self)
11 def public(self):
12 print(" 共有函數")
---> 13 self.__hide()
14
15 example().public()
AttributeError: 'example' object has no attribute '_example__hide'
以上是個人總結的相關python的基礎類實例,繼承,私有函數,私有變量等。
此外關於靜態方法,類方法和實例方法內容,可以參考:Python-實例方法靜態方法類方法對比總結(附Python代碼)