類相當(dāng)于一個(gè)容器,將狀態(tài)(數(shù)據(jù)屬性)和一些行為(方法)包裹在一起,今天我們就來(lái)講講Python中的方法.
Python中的方法分為3種,一般的書(shū)對(duì)這幾個(gè)概念都沒(méi)有仔細(xì)講,我覺(jué)得把這些概念弄清楚,對(duì)深入了解類是很有必要的,不然設(shè)計(jì)類的時(shí)候根本寫(xiě)不出真正的OOP.
在Python中定義類的方法和函數(shù)都使用def語(yǔ)句,就像定義其他的函數(shù)一樣來(lái)指定其行為.本質(zhì)上方法其實(shí)就是函數(shù)
要點(diǎn):
類的實(shí)例方法
類的靜態(tài)函數(shù)
類方法
類方法,靜態(tài)函數(shù),實(shí)例方法之間調(diào)用關(guān)系
1.類的實(shí)例方法
類的實(shí)例方法一般有一個(gè)顯著的特征就是會(huì)帶有self參數(shù),它的第一個(gè)正式參數(shù)名為self(這參數(shù)有點(diǎn)類似java里面的this),這些方法會(huì)訪問(wèn)實(shí)例的屬性.
看下面的實(shí)例代碼:
揭秘一下這個(gè)調(diào)用的過(guò)程:
1).step1,step2把參數(shù)'arun','seema'傳給__init__()里面的data
2).step3 self參數(shù)就是ik1對(duì)象實(shí)例的引用
3).在step4調(diào)用printd()這個(gè)實(shí)例函數(shù)的時(shí)候,我們不需要把ik1傳遞self,python自動(dòng)幫你搞定
2.類的靜態(tài)函數(shù)
類中的方法一般有self的方法也叫綁定對(duì)象方法,那Python中有沒(méi)有不帶self,當(dāng)然有的,靜態(tài)函數(shù)方法就是其中一個(gè)
靜態(tài)方法需要有一個(gè)修飾關(guān)鍵字staticmethod,注意前面有一個(gè)@,連起來(lái)@staticmethod表示下面聲明的是一個(gè)靜態(tài)函數(shù)方法,
這是Python中的一種特殊用法,其實(shí)就是用了一個(gè)裝飾器的技巧(關(guān)于裝飾器是Python中復(fù)雜的概念之一,本文先不講后面會(huì)詳細(xì)給大家講,大家在用web框架比如flask里面會(huì)大量用到裝飾器的概念)
那么Python中為啥要有靜態(tài)函數(shù)呢:
場(chǎng)景就是和類相關(guān)的操作,但是又不會(huì)依賴和改變類、實(shí)例的狀態(tài),比如經(jīng)常有跟類有關(guān)系的函數(shù),我們希望它在運(yùn)行時(shí)又不需要實(shí)例和類參與的情況下直接就能調(diào)用。調(diào)用靜態(tài)方法可以無(wú)需創(chuàng)建對(duì)象
舉個(gè)簡(jiǎn)單的例子:
有一個(gè)機(jī)器人的類,有兩個(gè)方法重啟(do_Reset)和保存數(shù)據(jù)庫(kù)(save_DB),這兩個(gè)方法操作之前都需要檢查指令
robot1 = Robot('No1_Machine')
robot1.do_Reset()
robot1.save_DB()
>>
Reset done for :No1_Machine
DB connection ready for: No1_Machine
robot2 = Robot('No2_Machine')
robot2.do_Reset()
robot2.save_DB()
>>
Reset done for :No2_Machine
DB connection ready for: No2_Machine
這樣是不是很麻煩,能不能把這個(gè)check_Indication()放到類里面,并且讓類的所有對(duì)象都能方便共享呢,有同學(xué)說(shuō)簡(jiǎn)單,挪進(jìn)來(lái),然后再把調(diào)用check_Indication的地方變成Robot.check_Indication()
robot1 = Robot('No1_Machine')
robot1.do_Reset()
>>
TypeError: unbound method check_Indication() must be called
with Robot instance as first argument (got nothing instead)
直接報(bào)錯(cuò),根本不行,這個(gè)時(shí)候靜態(tài)函數(shù)就可以派上用場(chǎng)了
robot1 = Robot('No1_Machine')
robot1.do_Reset()
robot1.save_DB()
robot2 = Robot('No2_Machine')
robot2.do_Reset()
robot2.save_DB()
>>
Reset done for :No1_Machine
DB connection ready for: No1_Machine
Reset done for :No2_Machine
DB connection ready for: No2_Machine
3.類方法
類的方法就叫類方法,當(dāng)我們要寫(xiě)一個(gè)只在類中運(yùn)行而不在實(shí)例中運(yùn)行的方法.
比如我們想讓方法不在實(shí)例中運(yùn)行,就可以用到類方法.也是用裝飾器@classmethod來(lái)修飾的
舉個(gè)例子我們有一個(gè)Student類,我們想記錄有多少個(gè)學(xué)生
def get_num_of_instance(cls_obj):
return cls_obj.num_student
class Student(object):
num_student=0
def __init__(self):
Student.num_student+=1
s1=Student()
s2=Student()
total_num=get_num_of_instance(Student)
print total_num
>>
2
其實(shí)我完全可以在類里面建一個(gè)函數(shù),然后獲得類的引用去獲取類的變量,這樣不是很簡(jiǎn)單嗎:
class Student(object):
num_student=0
def __init__(self):
Student.num_student+=1
@classmethod
def get_num_of_instance(cls):
return cls.num_student
s1=Student()
s2=Student()
total_num=s1.get_num_of_instance()
print total_num
>>
2
total_num=s2.get_num_of_instance()
print total_num
>>
2
total_num=Student.get_num_of_instance()
print total_num
>>
2
這樣的好處是:
不管這個(gè)方式是從實(shí)例調(diào)用還是從類調(diào)用,它都用第一個(gè)參數(shù)把類傳遞過(guò)來(lái).聰明的同學(xué)發(fā)現(xiàn)其實(shí)類方法的作用和靜態(tài)函數(shù)很像,確實(shí)很像,接著往下看
4.類方法,靜態(tài)函數(shù),實(shí)例方法之間調(diào)用關(guān)系
1). 靜態(tài)方法在訪問(wèn)本類的成員時(shí),只允許訪問(wèn)靜態(tài)成員(即靜態(tài)成員變量和靜態(tài)方法),而不允許訪問(wèn)實(shí)例成員變量和實(shí)例方法;實(shí)例方法則無(wú)此限制
2).實(shí)例方法可以訪問(wèn)實(shí)例屬性和類屬性,也可以訪問(wèn)靜態(tài)方法和類方法.
3). 類方法可以被對(duì)象調(diào)用,也可以被實(shí)例調(diào)用;傳入的都是類對(duì)象,主要用于工廠方法,具體的實(shí)現(xiàn)就交給子類處理
3). 靜態(tài)方法參數(shù)沒(méi)有實(shí)例參數(shù) self, 也就不能調(diào)用實(shí)例參數(shù),實(shí)例方法