最近在學(xué)習(xí)類過(guò)程中耕姊,綁定方法這個(gè)概念沒有理解透徹高帖,所以在網(wǎng)上找了很多相關(guān)博客找御、文章研究到底是怎么一回事。因?yàn)橛械奈恼滤愂雠c我在python3.5版本實(shí)際實(shí)驗(yàn)中有些出入乳丰,所以經(jīng)過(guò)實(shí)踐后總結(jié)出以下結(jié)論掌测。
對(duì)于Python類中,方法的定義方式产园,我們可以歸納有4種類型:
1汞斧、不帶self、cls參數(shù)且不加裝飾器(staticmethod淆两、classmethod)
2断箫、正常的方法定義拂酣,帶self參數(shù)
3秋冰、類方法:加裝飾器(classmethod)
4、靜態(tài)方法:加裝飾器(staticmethod)
下面對(duì)每一種定義的方式進(jìn)行分析:
1婶熬、不帶self剑勾、cls參數(shù)且不加裝飾器(staticmethod埃撵、classmethod)
定義代碼如下:
class Student(object):
def func(name):
print('my name is {}'.format(name))
我們通過(guò)用類和實(shí)例分別調(diào)用該方法:
print(Student.func)
Student.func('Tom')
print(Student().func)
Student().func('Tom')
類調(diào)用output:
<function Student.func at 0x0000000000D7D268>
my name is Tom
[Finished in 0.1s]
實(shí)例調(diào)用output:
<bound method Student.func of <__main__.Student object at 0x0000000000D444A8>>
Traceback (most recent call last):
File "I:\MyProject\awesome-python3-webapp\www\for_test.py", line 11, in <module>
Student().func('Tom')
TypeError: func() takes 1 positional argument but 2 were given
[Finished in 0.2s with exit code 1]
從上面的輸出我們可以看出,此種定義方法虽另,如果用類來(lái)調(diào)用該方法暂刘,那么這個(gè)方法就只是一個(gè)函數(shù),不會(huì)像綁定方法一樣會(huì)自動(dòng)傳值捂刺。傳參只需按照正常的函數(shù)傳參即可谣拣;如果用實(shí)例來(lái)調(diào)用該方法,那么這個(gè)方法就是綁定(bound)的方法族展,既然是綁定方法森缠,那么就會(huì)自動(dòng)把Student()
自身作為第一個(gè)參數(shù)傳到方法中去,所以Student().func('Tom')
會(huì)傳實(shí)例Student()
以及'Tom'
兩個(gè)參數(shù)到此方法仪缸,但是由于此方法定義時(shí)只定義了一個(gè)參數(shù)贵涵,所以就會(huì)有上述的報(bào)錯(cuò)。
2恰画、正常的方法定義宾茂,帶self參數(shù)
定義代碼如下:
class Student(object):
def func(self, name):
print('my name is {}'.format(name))
類調(diào)用該方法:
print(Student.func)
Student.func('Tom')
output:
<function Student.func at 0x000000000070D268>
Traceback (most recent call last):
File "I:\MyProject\awesome-python3-webapp\www\for_test.py", line 8, in <module>
Student.func('Tom')
TypeError: func() missing 1 required positional argument: 'name'
[Finished in 0.2s with exit code 1]
用類調(diào)用該方法,跟第一種情況一樣拴还,依然是一個(gè)函數(shù)跨晴。因?yàn)榇撕瘮?shù)有兩參數(shù)(self
和name
),由于實(shí)參'Tom'
是傳到了形參self
自沧,所以輸出中提示調(diào)用func
方法少了name
參數(shù)坟奥。正確的調(diào)用方式為Student.func(Student(), 'Tom')
。
用實(shí)例調(diào)用該方法:
print(Student().func)
Student().func('Tom')
output:
<bound method Student.func of <__main__.Student object at 0x00000000006E44A8>>
my name is Tom
[Finished in 0.2s]
可以看出實(shí)例調(diào)用該方法拇厢,得到是綁定的方法爱谁,Student()
和Tom
參數(shù),分別傳給形參self
和name
孝偎。
其實(shí)第一種和第二種定義的方法是一樣的访敌,而他們的區(qū)別只是有沒有self
這個(gè)參數(shù)。只要是實(shí)例調(diào)用這個(gè)方法衣盾,都是綁定的方法寺旺。都會(huì)自動(dòng)將實(shí)例自身作為第一個(gè)參數(shù)傳遞進(jìn)去。self
這個(gè)參數(shù)势决,是大家約定俗成的一種參數(shù)命名阻塑,命名成a
或者b
都是可以的,只不過(guò)這樣命名會(huì)降低代碼的可讀性果复。下面要說(shuō)的類方法中的cls
參數(shù)也是這個(gè)道理陈莽。
3、類方法:加裝飾器(classmethod)
定義代碼如下:
class Student(object):
@classmethod
def func(cls, name):
print('my name is {} from {}'.format(name, cls.__name__))
用類和實(shí)例分別調(diào)用該方法:
print(Student.func)
Student.func('Tom')
print(Student().func)
Student().func('Tom')
output:
<bound method Student.func of <class '__main__.Student'>>
my name is Tom from Student
<bound method Student.func of <class '__main__.Student'>>
my name is Tom from Student
[Finished in 0.2s]
可以看出,此種定義方式走搁,用類或者實(shí)例調(diào)用独柑,都是綁定的方法。用類調(diào)用私植,會(huì)將類自身作為第一個(gè)參數(shù)傳遞到方法中忌栅。用實(shí)例調(diào)用,會(huì)將實(shí)例所屬的類作為第一個(gè)參數(shù)傳遞到方法中曲稼。
4索绪、靜態(tài)方法:加裝飾器(staticmethod)
定義代碼如下:
class Student(object):
@staticmethod
def func(name):
print('my name is {}'.format(name))
用類和實(shí)例分別調(diào)用該方法:
print(Student.func)
Student.func('Tom')
print(Student().func)
Student().func('Tom')
output:
<function Student.func at 0x0000000000D6D268>
my name is Tom
<function Student.func at 0x0000000000D6D268>
my name is Tom
[Finished in 0.2s]
從上面的輸出代碼中,可以看出贫悄,使用裝飾器staticmethod裝飾的函數(shù)者春,只是一個(gè)普通函數(shù),沒有綁定方法的自動(dòng)傳值功能清女,傳參只需按照正常的函數(shù)傳參即可钱烟。
綜合上面分析,我們可以總結(jié)如下:
1嫡丙、凡是類中的方法拴袭、函數(shù),如果沒有加裝飾器曙博,當(dāng)通過(guò)類來(lái)調(diào)用的時(shí)候拥刻,得到的是普通的函數(shù),當(dāng)通過(guò)實(shí)例來(lái)調(diào)用的時(shí)候父泳,得到的是綁定方法般哼;
2、加裝飾器classmethod的方法惠窄,無(wú)論是通過(guò)類或者實(shí)例來(lái)調(diào)用蒸眠,得到的都是綁定方法,python會(huì)自動(dòng)將類本身或者實(shí)例所屬的類作為第一個(gè)參數(shù)傳遞進(jìn)去杆融;
3楞卡、加裝飾器staticmethod的方法,通過(guò)類或者實(shí)例調(diào)用脾歇,得到的都是普通函數(shù)蒋腮。