Python學(xué)習(xí)目錄
- 在Mac下使用Python3
- Python學(xué)習(xí)之?dāng)?shù)據(jù)類型
- Python學(xué)習(xí)之函數(shù)
- Python學(xué)習(xí)之高級特性
- Python學(xué)習(xí)之函數(shù)式編程
- Python學(xué)習(xí)之模塊
- Python學(xué)習(xí)之面向?qū)ο缶幊?/a>
- Python學(xué)習(xí)之面向?qū)ο蟾呒壘幊?/a>
- Python學(xué)習(xí)之錯(cuò)誤調(diào)試和測試
- 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,簡稱OOP,是一種程序設(shè)計(jì)思想。OOP把對象作為程序的基本單元效扫,一個(gè)對象包含了數(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è)類繼承下來的
- 使用時(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)語言 vs 動(dòng)態(tài)語言:
對于靜態(tài)語言(例如Java)來說盲赊,如果需要傳入Animal
類型铣鹏,則傳入的對象必須是Animal
類型或者它的子類,否則哀蘑,將無法調(diào)用Animal
中的方法吝沫。對于Python這樣的動(dòng)態(tài)語言來說,則不一定需要傳入Animal
類型递礼。我們只需要保證傳入的對象有Animal
中的方法就可以了惨险。
對象信息
使用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è)對象是否是函數(shù)怎么辦?可以使用types
模塊中定義的常量将硝。
使用isinstance()
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
Tru
可以判斷一個(gè)變量是否是某些類型中的一種恭朗,比如上面的代碼就可以判斷是否是list或者tuple
使用dir()
如果要獲得一個(gè)對象的所有屬性和方法,可以使用dir()
函數(shù)依疼,它返回一個(gè)包含字符串的list痰腮,比如,獲得一個(gè)str對象的所有屬性和方法:
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
類似__xxx__
的屬性和方法在Python中都是有特殊用途的律罢,比如__len__
方法返回長度膀值。在Python中,如果你調(diào)用len()
函數(shù)試圖獲取一個(gè)對象的長度误辑,實(shí)際上沧踏,在len()
函數(shù)內(nèi)部,它自動(dòng)去調(diào)用該對象的__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
僅僅把屬性和方法列出來是不夠的潦匈,配合getattr()
阱高、setattr()
以及hasattr()
,我們可以直接操作一個(gè)對象的狀態(tài):
>>> 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.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
也可以獲得對象的方法:
>>> 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í)例都可以訪問到。來測試一下:
>>> 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)先級比類屬性高,因此昵济,它會(huì)屏蔽掉類的name屬性
Michael
>>> print(Student.name) # 但是類屬性并未消失智绸,用Student.name仍然可以訪問
Student
>>> del s.name # 如果刪除實(shí)例的name屬性
>>> print(s.name) # 再次調(diào)用s.name,由于實(shí)例的name屬性沒有找到访忿,類的name屬性就顯示出來了
Student