一、“類(lèi)”有關(guān)的知識(shí)
1. 面向?qū)ο蟪绦蛟O(shè)計(jì)(OPP,Object-Oriented Programming):是一種計(jì)算機(jī)編程架構(gòu),它認(rèn)為程序由一系列的對(duì)象組成。其中最核心的概念是類(lèi)和對(duì)象,類(lèi)是對(duì)現(xiàn)實(shí)世界的抽象,類(lèi)的實(shí)例被稱(chēng)為對(duì)象。
1) 中心思想:一切皆對(duì)象(Everything is an object.)
2)OPP = 對(duì)象+類(lèi)+繼承+多態(tài)+消息
3)主要目標(biāo):重用性、靈活性、擴(kuò)展性
2. 類(lèi):是一種用戶(hù)定義的數(shù)據(jù)類(lèi)型,就像基本的數(shù)據(jù)類(lèi)型byte、int、float等一樣,不同的是它是一種復(fù)雜的數(shù)據(jù)類(lèi)型。類(lèi)可以用來(lái)定義變量,創(chuàng)建對(duì)象,還可以派生子類(lèi)。
3. 每個(gè)類(lèi)都包含了數(shù)據(jù)說(shuō)明、一組用于操作數(shù)據(jù)或傳遞數(shù)據(jù)的函數(shù)。
4. 因?yàn)轭?lèi)的本質(zhì)是一種數(shù)據(jù)類(lèi)型,而不是數(shù)據(jù)。所以類(lèi)不存在于內(nèi)存中,不可以被直接操作,只有被實(shí)化為對(duì)象時(shí),才會(huì)變得可操作。
5. 類(lèi)的內(nèi)部封裝了屬性和方法,即成員數(shù)據(jù)和成員函數(shù)。它描述一個(gè)對(duì)象能夠做什么,以及做的方法。
6. Python支持面向?qū)ο蟮娜筇卣鳎悍庋b、繼承和多態(tài)。子類(lèi)繼承父類(lèi),同樣可以繼承到父類(lèi)的變量和方法。
二、定義類(lèi)
1. 定義類(lèi)的語(yǔ)法如下:
class 類(lèi)名:
執(zhí)行語(yǔ)句
零到多個(gè)類(lèi)變量
零到多個(gè)類(lèi)方法
例如:
#定義一個(gè)Person類(lèi)
>>> class Person:
’這是一個(gè)學(xué)習(xí)定義類(lèi)的案例‘ # 類(lèi)的說(shuō)明文檔,放在類(lèi)頭和頭體之間
#定義一個(gè)類(lèi)變量
hair ='black'
#定義一個(gè)構(gòu)建方法
def __init__(self,name='Jeff',age=8): # 兩個(gè)變量都有默認(rèn)值
self.name=name
self.age=age
#定義一個(gè)實(shí)例方法
def say(self,content):
print(content)
2. 類(lèi)名:從語(yǔ)法上講只要是一個(gè)合法的標(biāo)識(shí)符即可,但要考慮程序的可讀性,類(lèi)名要求是由一個(gè)或多個(gè)有意義的單詞組成,每個(gè)單詞的首字母大寫(xiě),單詞和單詞之間不用任何人分隔符。
3. 定義類(lèi)需要注意的幾點(diǎn):
1)定義類(lèi)和定義函數(shù)類(lèi)似,只是類(lèi)用class關(guān)鍵字,函數(shù)用def關(guān)鍵字。
2)類(lèi)頭包含了class關(guān)鍵字和類(lèi)名,對(duì)冒號(hào)(:)作為類(lèi)的開(kāi)始,類(lèi)體包含了類(lèi)變量和方法,如果不為類(lèi)定義任意變量和方法,則為一個(gè)空類(lèi),用pass作為占位符。例如:
>>>class Empty:
pass
3) 類(lèi)所包含的類(lèi)變量可以動(dòng)態(tài)的增加或刪除。程序也可以為已有的對(duì)象增加或刪除實(shí)例變量。
4)在類(lèi)中定義的方法默認(rèn)是實(shí)例方法,定義實(shí)例方法和定義函數(shù)基本想同,實(shí)例方法至少應(yīng)該定義一個(gè)參數(shù),該參數(shù)通常被命名為self。
三、創(chuàng)建對(duì)象
1. 創(chuàng)建對(duì)象:調(diào)用某個(gè)類(lèi)的方法,即可創(chuàng)建這個(gè)類(lèi)的對(duì)象。例如:
#接上面的代碼
#將類(lèi)的Person對(duì)象賦值給變量p
>>>p=Person()
2. 創(chuàng)建完對(duì)象,就可以使用該對(duì)象了。Python的對(duì)象有如下作用:
1)操作對(duì)象的實(shí)例變量:訪問(wèn)實(shí)例變量的值,增加、修改、刪除實(shí)例變量。
#接上面的代碼
#直接輸出對(duì)象p的實(shí)例變量name 和 age的值
>>> print(p.name,p.age)? #結(jié)果:Jeff 8
#訪問(wèn)p的實(shí)例變量name ,給它重新賦值
>>>p.name='Mary'
2)操作對(duì)象的方法:調(diào)用方法,添加或刪除方法。
#調(diào)用P的say()方法
p.say('welcome to yanghang robot')
#再次輸出對(duì)象p的實(shí)例變量name 和 age的值
>>>print(p.name,p.age) #結(jié)果:Mary 8
3. 對(duì)象的動(dòng)態(tài)性:
1)動(dòng)態(tài)增加或刪除對(duì)象的實(shí)例變量,例如;
# 直接給對(duì)象的變量賦值就可以增加變量
>>> p.skills=['dancing','swimming']
>>> print(p.skills)? #結(jié)果: ['dancing', 'swimming']
#使用del語(yǔ)句,就可以刪除對(duì)象的變量
>>> del p.name
>>> print(p.name)
#結(jié)果報(bào)錯(cuò):AttributeError: 'Person' object has no attribute 'name'
2)動(dòng)態(tài)的增加和刪除方法,例如:
#P對(duì)象動(dòng)態(tài)增加的方法不會(huì)自行綁定第一個(gè)參數(shù)self
#先定義一個(gè)函數(shù) info()
>>> def info(self): p
print('--info--函數(shù)',self)
# 使用info() 函數(shù)給 對(duì)象p 的方法賦值,就動(dòng)態(tài)增加了方法
>>> p.info=info
>>> p.info(p)? #程序必需手動(dòng)傳入?yún)?shù)
# 使用lambda表達(dá)式 給 對(duì)象p 的方法賦值,就動(dòng)態(tài)增加了方法
>>> p.bar= lambda self: print('---lambda---',self)
>>> p.bar(p) #程序必需手動(dòng)傳入?yún)?shù)
4. 方法之間的依賴(lài):
1) 類(lèi)體中方法的第一個(gè)參數(shù)self, 會(huì)被自動(dòng)綁定給對(duì)象,所以不需要給第一個(gè)參數(shù)傳值。
2) 方法的第一個(gè)參數(shù)所代表的對(duì)象是不確定的,也就是誰(shuí)調(diào)用該方法,第一個(gè)參數(shù)就代表誰(shuí)。例如:
#定義一個(gè)dog類(lèi)
>>> class dog:
#定義一個(gè)jump方法
def jump(self):
print('jump......')
#定義一個(gè)run方法,run方法調(diào)用了jump方法
# run 和 jump 之間就存在依賴(lài)
def run (self):
self.jump()
print('run.......')
3)在構(gòu)造方法中,self參數(shù)代表該構(gòu)建方法正在初始化的對(duì)象。
四、類(lèi)方法和靜態(tài)方法
1. 方法:是類(lèi)或?qū)ο蟮男袨樘卣鞯某橄螅?Python中方法其實(shí)也是函數(shù),所以其定義方法和調(diào)用形式都和函數(shù)類(lèi)似。
2. 使用類(lèi)調(diào)用方法:之前的例子都是對(duì)象調(diào)用方法,如果類(lèi)直接調(diào)用方法,就不會(huì)自動(dòng)綁定self參數(shù),所以要手動(dòng)傳入?yún)?shù),例如:
#定義一個(gè)類(lèi)user
>>> class user:
#定義一個(gè)方法 walk
def walk(self):
print(self,'walking....')
#使用類(lèi)直接調(diào)用方法
>>> user.walk()
#結(jié)果報(bào)錯(cuò):TypeError: walk() missing 1 required positional argument: 'self'
#手動(dòng)傳入?yún)?shù)值'abc'
>>> user.walk('abc')
# 結(jié)果:abc walking....
3. 類(lèi)方法和靜態(tài)方法的區(qū)別:
1)類(lèi)方法的第一個(gè)參數(shù)會(huì)自動(dòng)綁定到類(lèi)本身;而靜態(tài)方法不會(huì)綁定到類(lèi)。
2)使用@classmethod修飾的方法是類(lèi)方法;使用@staticmethod修飾的方法為靜態(tài)方法。例如:
#定義一個(gè)bird類(lèi)
>>> class bird:
#用@classmethod修飾類(lèi)方法fly
@classmethod
def fly(cls):
print('類(lèi)方法fly',cls)
#用@staticmethod修飾靜態(tài)方法info
@staticmethod
def info(p):
print('靜態(tài)方法info',p)
#類(lèi)直接調(diào)用 類(lèi)方法fly,不需要傳入?yún)?shù)
>>> bird.fly() #結(jié)果:類(lèi)方法fly
#類(lèi)調(diào)用info方法,需要手動(dòng)傳入?yún)?shù)
>>> bird.info('abc') #結(jié)果: 靜態(tài)方法info abc
# 構(gòu)建對(duì)象和調(diào)用方法
>>> b=bird
>>> b.fly()
>>> b.info('abc')
4. @函數(shù)裝飾器
1)@classmethod和@staticmethod就是函數(shù)裝飾器,classmethod和 staticmethod都是Python內(nèi)置的函數(shù)。
2)使用@符號(hào)引用已有的函數(shù),可以用來(lái)修飾其它函數(shù)。我們也可以開(kāi)發(fā)自定義的函數(shù)修飾器。
3)當(dāng)一個(gè)函數(shù)裝飾另一個(gè)函數(shù)時(shí),實(shí)際上是完成了以下兩步:
被裝飾的函數(shù)B, 作為參數(shù)被傳給了@符號(hào)所引用的函數(shù)A
將函數(shù)B替換成了上一步的返回值,所以函數(shù)B已經(jīng)不是原來(lái)的函數(shù)。
>>> def funA(fn):
print('A')
?return 'Jeff'
>>> @funA? #裝飾的效果相當(dāng)于funA(funB),將funB做為了funA的參數(shù),返回了'Jeff'
def funB():
print('B')
>>> print(funB)
# funB已經(jīng)不再是一個(gè)函數(shù),而是一個(gè)字符串,運(yùn)行結(jié)果Jeff
六、本節(jié)回顧
1) 關(guān)于類(lèi)的知識(shí)你知道了哪些?
2)如何定義一個(gè)類(lèi)?
3)如何構(gòu)建類(lèi)的對(duì)象和使用對(duì)象?
4)如何添加、刪除、修改方法?
5)類(lèi)方法和靜態(tài)方法的區(qū)別?
6)@函數(shù)裝飾器的用法?