Python學(xué)習(xí)目錄
- 在Mac下使用Python3
- Python學(xué)習(xí)之?dāng)?shù)據(jù)類型
- Python學(xué)習(xí)之函數(shù)
- Python學(xué)習(xí)之高級(jí)特性
- Python學(xué)習(xí)之函數(shù)式編程
- Python學(xué)習(xí)之模塊
- Python學(xué)習(xí)之面向?qū)ο缶幊?/a>
- Python學(xué)習(xí)之面向?qū)ο蟾呒?jí)編程
- Python學(xué)習(xí)之錯(cuò)誤調(diào)試和測(cè)試
- Python學(xué)習(xí)之IO編程
- Python學(xué)習(xí)之進(jìn)程和線程
- Python學(xué)習(xí)之正則
- Python學(xué)習(xí)之常用模塊
- 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