1. 程式人生 > >Python面向物件基礎

Python面向物件基礎

NOTE:重要強調:    Python的作用域和名稱空間(1)名稱空間 是從命名到物件的對映    ①內建名稱空間    ②全域性名稱空間:模組    ③本地名稱空間:模組中的函式和類(2)作用域   是一個 Python 程式可以直接訪問名稱空間的正文區域    一:簡介            類:用來描述具有相同的屬性和方法的物件的集合        方法:類中定義的函式      類變數:類變數在整個例項化的物件中是公用的。                    類變數定義在類中且在函式體之外。類變數通常不作為例項變數使用。    例項變數:定義在方法中的變數,只作用於當前例項的類。(注意區分例項變數和類變數)    例項變數用於對每一個例項都是唯一的資料,類變數用於類的所有例項共享的屬性和方法    用構造方法初始化的屬性叫做例項變數,直接在類中定義的屬性叫做類變數。   方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override)       例項化:建立一個類的例項,類的具體物件           物件:通過類定義的資料結構例項    二:語法格式        class ClassName:            <statement-1>            <statement-N>三:類物件    類物件支援兩種操作:屬性引用和例項化。    (1)類物件建立後,類名稱空間中所有的命名都是有效屬性名MyClass.f    (2)例項化:將類物件看作是一個返回新的類例項的無引數函式x = MyClass()    四:類屬性    公有屬性:在類中定義,可以在類間呼叫,可以通過解構函式進行初始化    私有屬性:在類中定義,以雙下劃線開始,在類外不能被直接呼叫,只能被類內部方法使用!    呼叫方法:用公有方法返回!五:類方法    (1)類的方法與普通的函式只有一個特別的區別——它們必須有一個額外的第一個引數名稱,     按照慣例它的名稱是 self    (2)在類的內部,使用 def 關鍵字來定義一個方法,與一般函式定義不同,    類方法必須包含引數 self, 且為第一個引數,self 代表的是類的例項    (3)兩個下劃線開頭,宣告該方法為私有方法,只能在類的內部呼叫 ,不能在類地外部呼叫    (4)類的專有方法六:建構函式    類有一個名為 __init__() 的特殊方法(構造方法),    該方法在類例項化時會自動呼叫類有一個名為 __init__() 的特殊方法(構造方法),    該方法在類例項化時會自動呼叫    可以宣告帶預設引數的例項變數!七:解構函式    例項化的物件呼叫結束時候呼叫!八:類的繼承        (1)語法結構        class DerivedClassName(BaseClassName1):                    <statement-1>                    .                    <statement-N>        (2)多類繼承的時候,新式類(python3)按照廣度優先的原則,        (找一個爸爸,再找下一個爸爸。。。。)            class DerivedClassName(Base1, Base2, Base3):                <statement-1>                .                    <statement-N>    (3)基類名與派生類定義在同一個作用域中,除了類,還可以用表示式,    基類定義在另一個模組中時這一點非常有用:         class DerivedClassName(modname.BaseClassName):    這種寫法在模組化程式中很重要!    (4)方法重寫    ①父類方法的功能不能滿足你的需求,可以在子類重寫你父類的方法        super(Child,c).myMethod() #用子類物件呼叫父類已被覆蓋的方法          子類,物件, 方法    ②派生類對基類的方法重寫,重寫後的基類方法叫做費捆綁方法,    不能直接呼叫,需要使用super函式。    注意:    ①子類不重寫 __init__,例項化子類時,會自動呼叫父類定義的 __init__。    ②重寫了__init__ 時,例項化子類,就不會呼叫父類已經定義的 __init__    ③如果重寫了__init__ 時,要繼承父類的構造方法,可以使用 super 關鍵字        super(子類,self).__init__(引數1,引數2,....)        父類名稱.__init__(self,引數1,引數2,...)    八:多型和封裝    “當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。”    在鴨子型別中,關注的不是物件的型別本身,而是它是如何使用的。    例如,在不使用鴨子型別的語言中,我們可以編寫一個函式,它接受一個型別為鴨的物件,    並呼叫它的走和叫方法。在使用鴨子型別的語言中,這樣的一個函式可以接受一個任意型別的物件,    並呼叫它的走和叫方法。如果這些需要被呼叫的方法不存在,那麼將引發一個執行時錯誤。    任何擁有這樣的正確的走和叫方法的物件都可被函式接受的這種行為引出了以上表述,    這種決定型別的方式因此得名。    http://www.php.cn/python-tutorials-366356.html    (關於多型不是太懂!)

  1 # -------------------------------------------------------------------------------------------------------------#
  2 # 建立類
  3 # -------------------------------------------------------------------------------------------------------------#
  4 
  5 
  6 class MyClass:                      # 類的命名為大駝峰原則
7 """一個簡單的類例項""" 8 i = 12345 # 類的公有屬性 9 10 def __init__(self, real): # 帶引數的建構函式(方法) 11 self.r = real 12 # self.i = imag 13 14 def func(self): # 類的方法和普通函式的區別 15 m = self.i + self.r 16 return
m 17 # -------------------------------------------------------------------------------------------------------------# 18 # 類的例項化 19 # -------------------------------------------------------------------------------------------------------------# 20 21 22 print("------------------------類的例項化-----------------------------------") 23 x = MyClass(2) 24 y = MyClass(3) 25 # print(x.__doc__) 26 # 訪問類的屬性和方法 27 print("MyClass 類的屬性 i 為:", x.i) 28 print("MyClass 類的屬性 i 為:", y.i) 29 30 # 對於可變物件如列表、字典、集合,應該宣告為例項變數,因為例項化後的物件會改變原來的值! 31 x.i = 23 32 print("例項化X後 i 為:", x.i) 33 print("例項化Y後 i 為:", y.i) 34 print("MyClass 類的方法 f 輸出為:", x.func()) 35 36 # -------------------------------------------------------------------------------------------------------------# 37 # 類的繼承 38 # -------------------------------------------------------------------------------------------------------------# 39 print("------------------------類的繼承-------------------------------------") 40 41 42 # 定義基類 43 class People: 44 # 定義類變數 45 # name = '' 46 # age = 0 47 # 定義私有屬性,私有屬性在類外部無法直接進行訪問 48 # __weight = 0 49 # 定義構造方法,初始化類變數的值 50 51 def __init__(self, n, a, w): # 建構函式 52 # print('呼叫了建構函式') # 測試建構函式的呼叫 53 self.name = n 54 self.age = a 55 self.__weight = w 56 # 上面的變數可以全部定義為私有變數!因為在外部沒有必要使用! 57 58 def speak(self): 59 print("%s 說: ’我 %d 歲 %dkg’" % (self.name, self.age, self.__weight)) 60 61 def my_print(self, name): 62 print(self.name) # self的作用是類級別上的變數 63 print(name) # 不帶self可能是變數的值 64 65 def get_name(self): # OPP家族傳統理念:Getter + Setter 66 return self.name # 為了得到類中的資料並且抱枕資料的安全(無受保護的資料型別) 67 68 def get_age(self): # 通過self實現內容的間接呼叫 69 return self.age 70 71 # @property # 72 def get_weight(self): # 通過self實現內容的間接呼叫 73 return self.__weight 74 75 def __del__(self): # 注意學習python的垃圾回收機制 76 print('呼叫了父解構函式') 77 # 總結:對於面向物件的封裝來說,其實就是使用構造方法將內容封裝到物件中, 78 # 通過物件或者self間接的呼叫內容 79 80 # 繼承:子可以繼承父親的所有內容 81 # 定義派生類 82 83 84 class Student(People): 85 86 def __init__(self, n, a, w, g): 87 self.__grade = g 88 People.__init__(self, n, a, w) # 呼叫父類的建構函式 89 90 # 保變數的值不被改變 ,又要得到值 91 def lo_ol(self): 92 print('I am not a good student!') 93 print('My grade is %d' % self.__grade) 94 95 def __del__(self): # 注意學習python的垃圾回收機制 96 print('呼叫了子解構函式') 97 98 99 myInfo = People('faith', 24, 60) 100 myInfo.speak() 101 myInfo.age = 10 102 myInfo.speak() 103 print(myInfo.age) # 類外直接使用 104 105 106 print("------------------------測試派生類-------------------------------------") 107 # 通過上面的程式碼可以得到下面的結論: 108 # 解構函式在物件釋放的時候呼叫 109 # 可以直接在類外訪問類的基本屬性 110 # 不能在類外直接訪問類的私有屬性 111 112 stud = Student('faith', 2, 2, 2) 113 stud.lo_ol() 114 stud.speak() 115 print("體重", stud.get_weight()) 116 # 方法重寫 117 118 119 class Parent: # 定義父類 120 def mymethod(self): 121 print('呼叫父類方法') 122 123 124 class Child(Parent): # 定義子類 125 def mymethod(self): 126 print('呼叫子類方法') 127 128 129 print("------------------------測試方法重寫-------------------------------------") 130 c = Child() # 子類例項 131 c.mymethod() # 子類呼叫重寫方法 132 super(Child, c).mymethod() # 用子類物件呼叫父類已被覆蓋的方法 133 134 # 靜態方法和類方法 135 print("------------------------測試靜態方法和類方法-------------------------------------") 136 137 138 class Apple: 139 def fun1(self): 140 return 'normal' 141 142 @staticmethod # 靜態方法 143 def fun2(): 144 return 'staticmethod' 145 146 @classmethod 147 def fun3(cls): # 類方法(能夠訪問類屬性) 148 return 'classmethod' 149 150 151 print(Apple.fun1) # 非捆綁呼叫 152 print(Apple.fun2) 153 print(Apple.fun3) 154 print("-"*80) 155 156 157 apple = Apple() # 捆綁呼叫 158 print(apple.fun1) 159 print(apple.fun2) 160 print(apple.fun3) 161 162 print("-"*80) 163 164 apple1 = Apple() # 捆綁呼叫 165 print(apple1.fun1) 166 print(apple1.fun2) 167 print(apple1.fun3)