第11課 類(lèi)和對(duì)象(2019-12-03)

一、“類(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ù)裝飾器的用法?

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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