Python學習之物件導向程式設計

stonezhu發表於2018-06-17

Python學習目錄

  1. 在Mac下使用Python3
  2. Python學習之資料型別
  3. Python學習之函式
  4. Python學習之高階特性
  5. Python學習之函數語言程式設計
  6. Python學習之模組
  7. Python學習之物件導向程式設計
  8. Python學習之物件導向高階程式設計
  9. Python學習之錯誤除錯和測試
  10. Python學習之IO程式設計
  11. Python學習之程式和執行緒
  12. Python學習之正則
  13. Python學習之常用模組
  14. Python學習之網路程式設計

物件導向程式設計——Object Oriented Programming,簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和運算元據的函式。

類和例項

定義

class Student(object):    passstone = Student()stone.name = "stone"stone.age = 2print(stone.name, stone.age)複製程式碼

上面程式碼中:

  • class後面緊接的是類名,類名以大寫字母開頭
  • (object)是該類從哪個類繼承下來的
  • 使用時候可以自由的給例項變數繫結屬性

方法

class Student(object):    def __init__(self, name, age):        self.name = name        self.age = age    def print_info(self):        print(self.name, self.age)        stone = Student("stone", 18)stone.print_info()複製程式碼

上面程式碼中:

  • __init__方法的第一個引數永遠是self,表示建立的例項本身,因此,在__init__方法內部,就可以把各種屬性繫結到self,因為self就指向建立的例項本身。類似於java的建構函式。
  • 定義一個方法,除了第一個引數是self外,其他和普通函式一樣。要呼叫一個方法,只需要在例項變數上直接呼叫,除了self不用傳遞,其他引數正常傳入。

訪問限制

  • 例項的變數名如果以__開頭,就變成了一個私有變數(private),只有內部可以訪問,外部不能訪問。
  • 變數名類似__xxx__的,也就是以雙下劃線開頭,並且以雙下劃線結尾的,是特殊變數,特殊變數是可以直接訪問的,不是private變數。

繼承和多型

在OOP程式設計中,當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class)。和java一樣。

靜態語言 vs 動態語言:

對於靜態語言(例如Java)來說,如果需要傳入Animal型別,則傳入的物件必須是Animal型別或者它的子類,否則,將無法呼叫Animal中的方法。對於Python這樣的動態語言來說,則不一定需要傳入Animal型別。我們只需要保證傳入的物件有Animal中的方法就可以了。

物件資訊

使用type()

>
>
>
import types>
>
>
def fn():... pass...>
>
>
type(fn)==types.FunctionTypeTrue>
>
>
type(abs)==types.BuiltinFunctionTypeTrue>
>
>
type(lambda x: x)==types.LambdaTypeTrue>
>
>
type((x for x in range(10)))==types.GeneratorTypeTrue複製程式碼

以上程式碼可以看出,判斷基本資料型別可以直接寫intstr等,但如果要判斷一個物件是否是函式怎麼辦?可以使用types模組中定義的常量。

使用isinstance()

>
>
>
isinstance([1, 2, 3], (list, tuple))True>
>
>
isinstance((1, 2, 3), (list, tuple))Tru複製程式碼

可以判斷一個變數是否是某些型別中的一種,比如上面的程式碼就可以判斷是否是list或者tuple

使用dir()

如果要獲得一個物件的所有屬性和方法,可以使用dir()函式,它返回一個包含字串的list,比如,獲得一個str物件的所有屬性和方法:

>
>
>
dir('ABC')['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']複製程式碼

類似__xxx__的屬性和方法在Python中都是有特殊用途的,比如__len__方法返回長度。在Python中,如果你呼叫len()函式試圖獲取一個物件的長度,實際上,在len()函式內部,它自動去呼叫該物件的__len__()方法,所以,下面的程式碼是等價的:

>
>
>
len('ABC')3>
>
>
'ABC'.__len__()3複製程式碼

我們自己寫的類,如果也想用len(myObj)的話,就自己寫一個__len__()方法:

>
>
>
class MyDog(object):... def __len__(self):... return 100...>
>
>
dog = MyDog()>
>
>
len(dog)100複製程式碼

僅僅把屬性和方法列出來是不夠的,配合getattr()setattr()以及hasattr(),我們可以直接操作一個物件的狀態:

>
>
>
class MyObject(object):... def __init__(self):... self.x = 9... def power(self):... return self.x * self.x...>
>
>
obj = MyObject()複製程式碼

緊接著,可以測試該物件的屬性:

>
>
>
hasattr(obj, 'x') # 有屬性'x'嗎?True>
>
>
obj.x9>
>
>
hasattr(obj, 'y') # 有屬性'y'嗎?False>
>
>
setattr(obj, 'y', 19) # 設定一個屬性'y'>
>
>
hasattr(obj, 'y') # 有屬性'y'嗎?True>
>
>
getattr(obj, 'y') # 獲取屬性'y'19>
>
>
obj.y # 獲取屬性'y'19複製程式碼

也可以獲得物件的方法:

>
>
>
hasattr(obj, 'power') # 有屬性'power'嗎?True>
>
>
getattr(obj, 'power') # 獲取屬性'power'<
bound method MyObject.power of <
__main__.MyObject object at 0x10077a6a0>
>
>
>
>
fn = getattr(obj, 'power') # 獲取屬性'power'並賦值到變數fn>
>
>
fn # fn指向obj.power<
bound method MyObject.power of <
__main__.MyObject object at 0x10077a6a0>
>
>
>
>
fn() # 呼叫fn()與呼叫obj.power()是一樣的81複製程式碼

例項屬性和類屬性

類本身需要繫結一個屬性:

class Student(object):    name = 'Student'複製程式碼

當我們定義了一個類屬性後,這個屬性雖然歸類所有,但類的所有例項都可以訪問到。來測試一下:

>
>
>
class Student(object):... name = 'Student'...>
>
>
s = Student() # 建立例項s>
>
>
print(s.name) # 列印name屬性,因為例項並沒有name屬性,所以會繼續查詢class的name屬性Student>
>
>
print(Student.name) # 列印類的name屬性Student>
>
>
s.name = 'Michael' # 給例項繫結name屬性>
>
>
print(s.name) # 由於例項屬性優先順序比類屬性高,因此,它會遮蔽掉類的name屬性Michael>
>
>
print(Student.name) # 但是類屬性並未消失,用Student.name仍然可以訪問Student>
>
>
del s.name # 如果刪除例項的name屬性>
>
>
print(s.name) # 再次呼叫s.name,由於例項的name屬性沒有找到,類的name屬性就顯示出來了Student複製程式碼

下一篇:Python學習之物件導向高階程式設計

來源:https://juejin.im/post/5b267547518825749864a1b7

相關文章