Python學(xué)習(xí)之面向?qū)ο缶幊?/h2>

Python學(xué)習(xí)目錄

  1. 在Mac下使用Python3
  2. Python學(xué)習(xí)之?dāng)?shù)據(jù)類型
  3. Python學(xué)習(xí)之函數(shù)
  4. Python學(xué)習(xí)之高級(jí)特性
  5. Python學(xué)習(xí)之函數(shù)式編程
  6. Python學(xué)習(xí)之模塊
  7. Python學(xué)習(xí)之面向?qū)ο缶幊?/a>
  8. Python學(xué)習(xí)之面向?qū)ο蟾呒?jí)編程
  9. Python學(xué)習(xí)之錯(cuò)誤調(diào)試和測(cè)試
  10. Python學(xué)習(xí)之IO編程
  11. Python學(xué)習(xí)之進(jìn)程和線程
  12. Python學(xué)習(xí)之正則
  13. Python學(xué)習(xí)之常用模塊
  14. Python學(xué)習(xí)之網(wǎng)絡(luò)編程

面向?qū)ο缶幊獭狾bject Oriented Programming,簡(jiǎn)稱OOP,是一種程序設(shè)計(jì)思想。OOP把對(duì)象作為程序的基本單元,一個(gè)對(duì)象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)。

類和實(shí)例

定義

class Student(object):
    pass

stone = Student()
stone.name = "stone"
stone.age = 2

print(stone.name, stone.age)

上面代碼中:

  • class后面緊接的是類名,類名以大寫字母開頭
  • (object)是該類從哪個(gè)類繼承下來(lái)的
  • 使用時(shí)候可以自由的給實(shí)例變量綁定屬性

方法

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__方法的第一個(gè)參數(shù)永遠(yuǎn)是self,表示創(chuàng)建的實(shí)例本身,因此,在__init__方法內(nèi)部,就可以把各種屬性綁定到self,因?yàn)?code>self就指向創(chuàng)建的實(shí)例本身。類似于java的構(gòu)造函數(shù)。
  • 定義一個(gè)方法,除了第一個(gè)參數(shù)是self外,其他和普通函數(shù)一樣。要調(diào)用一個(gè)方法,只需要在實(shí)例變量上直接調(diào)用,除了self不用傳遞,其他參數(shù)正常傳入。

訪問限制

  • 實(shí)例的變量名如果以__開頭,就變成了一個(gè)私有變量(private),只有內(nèi)部可以訪問,外部不能訪問。
  • 變量名類似__xxx__的,也就是以雙下劃線開頭,并且以雙下劃線結(jié)尾的,是特殊變量,特殊變量是可以直接訪問的,不是private變量。

繼承和多態(tài)

在OOP程序設(shè)計(jì)中,當(dāng)我們定義一個(gè)class的時(shí)候,可以從某個(gè)現(xiàn)有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class)。和java一樣。

靜態(tài)語(yǔ)言 vs 動(dòng)態(tài)語(yǔ)言:

對(duì)于靜態(tài)語(yǔ)言(例如Java)來(lái)說,如果需要傳入Animal類型,則傳入的對(duì)象必須是Animal類型或者它的子類,否則,將無(wú)法調(diào)用Animal中的方法。對(duì)于Python這樣的動(dòng)態(tài)語(yǔ)言來(lái)說,則不一定需要傳入Animal類型。我們只需要保證傳入的對(duì)象有Animal中的方法就可以了。

對(duì)象信息

使用type()

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

以上代碼可以看出,判斷基本數(shù)據(jù)類型可以直接寫int,str等,但如果要判斷一個(gè)對(duì)象是否是函數(shù)怎么辦?可以使用types模塊中定義的常量。

使用isinstance()

>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
Tru

可以判斷一個(gè)變量是否是某些類型中的一種,比如上面的代碼就可以判斷是否是list或者tuple

使用dir()

如果要獲得一個(gè)對(duì)象的所有屬性和方法,可以使用dir()函數(shù),它返回一個(gè)包含字符串的list,比如,獲得一個(gè)str對(duì)象的所有屬性和方法:

>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']

類似__xxx__的屬性和方法在Python中都是有特殊用途的,比如__len__方法返回長(zhǎng)度。在Python中,如果你調(diào)用len()函數(shù)試圖獲取一個(gè)對(duì)象的長(zhǎng)度,實(shí)際上,在len()函數(shù)內(nèi)部,它自動(dòng)去調(diào)用該對(duì)象的__len__()方法,所以,下面的代碼是等價(jià)的:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

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

>>> class MyDog(object):
...     def __len__(self):
...         return 100
...
>>> dog = MyDog()
>>> len(dog)
100

僅僅把屬性和方法列出來(lái)是不夠的,配合getattr()、setattr()以及hasattr(),我們可以直接操作一個(gè)對(duì)象的狀態(tài):

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()

緊接著,可以測(cè)試該對(duì)象的屬性:

>>> hasattr(obj, 'x') # 有屬性'x'嗎?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
False
>>> setattr(obj, 'y', 19) # 設(shè)置一個(gè)屬性'y'
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
True
>>> getattr(obj, 'y') # 獲取屬性'y'
19
>>> obj.y # 獲取屬性'y'
19

也可以獲得對(duì)象的方法:

>>> 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() # 調(diào)用fn()與調(diào)用obj.power()是一樣的
81

實(shí)例屬性和類屬性

類本身需要綁定一個(gè)屬性:

class Student(object):
    name = 'Student'

當(dāng)我們定義了一個(gè)類屬性后,這個(gè)屬性雖然歸類所有,但類的所有實(shí)例都可以訪問到。來(lái)測(cè)試一下:

>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 創(chuàng)建實(shí)例s
>>> print(s.name) # 打印name屬性,因?yàn)閷?shí)例并沒有name屬性,所以會(huì)繼續(xù)查找class的name屬性
Student
>>> print(Student.name) # 打印類的name屬性
Student
>>> s.name = 'Michael' # 給實(shí)例綁定name屬性
>>> print(s.name) # 由于實(shí)例屬性優(yōu)先級(jí)比類屬性高,因此,它會(huì)屏蔽掉類的name屬性
Michael
>>> print(Student.name) # 但是類屬性并未消失,用Student.name仍然可以訪問
Student
>>> del s.name # 如果刪除實(shí)例的name屬性
>>> print(s.name) # 再次調(diào)用s.name,由于實(shí)例的name屬性沒有找到,類的name屬性就顯示出來(lái)了
Student

下一篇:Python學(xué)習(xí)之面向?qū)ο蟾呒?jí)編程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容