python類方法中的self關(guān)鍵字使用
之前學(xué)python爬蟲(chóng)的時(shí)候要把函數(shù)封裝到類里面,寫(xiě)成類方法,知道在python的類方法中第一個(gè)參數(shù)應(yīng)該是self,但對(duì)self代表的具體意義不甚了了。
最近在看Java,對(duì)面向?qū)ο缶幊痰牧私飧嗔艘稽c(diǎn),終于徹底弄明白self到底是什么了。
Python的類
在python中,所有的類都直接或間接繼承自O(shè)bject類,定義了類之后就定義了一個(gè)命名空間,里面定義的屬性可以通過(guò)類名來(lái)引用。
新定義的類中有一些Object中有的屬性,可以在其中定義其他變量或者函數(shù)。實(shí)例化之后會(huì)創(chuàng)建一個(gè)對(duì)象,該對(duì)象脫胎于類,并且其中的屬性動(dòng)態(tài)地和類中的屬性產(chǎn)生關(guān)聯(lián):
class A: pass a = A()
這段代碼創(chuàng)建了一個(gè)類A,并且對(duì)它進(jìn)行了實(shí)例化,實(shí)例化之后的對(duì)象綁定為變量a。
我可以看看A里面和a里面分別有什么:
In [38]: dir(A) Out[38]: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
In [39]: dir(a) Out[39]: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
用dir函數(shù)輸出A中和a中的屬性后,我們可以看到A和a中的屬性是一樣的。
我們可以向其中添加屬性,添加屬性時(shí)必須初始化:
In [40]: A.b --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-40-ebcfc7dbf31a> in <module>() ----> 1 A.b AttributeError: type object 'A' has no attribute 'b'
In [41]: A.b = 1
現(xiàn)在我們可以看看A和a中的屬性發(fā)生了什么變化:
In [42]: dir(A) Out[42]: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'b']
In [43]: dir(a) Out[43]: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'b']
In [74]: A.b Out[74]: 1 In [75]: a.b Out[75]: 1
我們可以看到,在A中和它的實(shí)例化對(duì)象中現(xiàn)在都有了屬性b,而且它們的值相等。
如果我們給A的實(shí)例化對(duì)象中添加屬性呢:
In [44]: a.c = 2 In [45]: hasattr(a, c) --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-45-15d927c71e90> in <module>() ----> 1 hasattr(a, c) NameError: name 'c' is not defined
竟然報(bào)錯(cuò)了,c沒(méi)有定義,報(bào)錯(cuò)的原因是A的實(shí)例化對(duì)象a的命名空間中有c,但是公共命名空間中沒(méi)有c,所以我們?cè)僭囈淮危?/p>
In [58]: c = a.c In [59]: hasattr(a, 'c') Out[59]: True In [60]: hasattr(A, 'c') Out[60]: False
我們可以看到,a中有c,但是A中并沒(méi)有c。是不是因?yàn)閏指向的是a.c所以A中沒(méi)有呢:
In [61]: b = a.b In [62]: hasattr(A, 'b') Out[62]: True
確實(shí)是因?yàn)樵陬惖膶?shí)例化對(duì)象中添加的屬性不會(huì)加入類中。
我們接著看給A或a中加入函數(shù)屬性會(huì)發(fā)生什么:
In [78]: A.foo = lambda x : x + 1 In [79]: A.foo(1) Out[79]: 2 In [80]: a.foo(1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-80-7dc85fd7a693> in <module>() ----> 1 a.foo(1) TypeError: <lambda>() takes 1 positional argument but 2 were given
python方法函數(shù)中的self關(guān)鍵字
上面執(zhí)行"a.foo(1)"語(yǔ)句時(shí)有個(gè)報(bào)錯(cuò),說(shuō)只需要一個(gè)參數(shù),但是給了兩個(gè)參數(shù),這第二個(gè)參數(shù)是怎么來(lái)的,為什么A.foo(1)就不會(huì)出錯(cuò)。
這里我們可以引出python類中的方法函數(shù),方法函數(shù)指的是通過(guò)類的實(shí)例化對(duì)象調(diào)用的函數(shù),方法函數(shù)的第一個(gè)形參表示類的實(shí)例化對(duì)象,通常寫(xiě)成self。
執(zhí)行a.foo(1)時(shí)就相當(dāng)于執(zhí)行A.foo(a,1),因?yàn)锳.foo()中只有一個(gè)形參,傳入的參數(shù)多于需要的參數(shù),所以發(fā)生類型錯(cuò)誤。
我們?cè)贏的定義中重新定義foo:
class A: def foo(self, n): print(n+1) a = A()
現(xiàn)在我們?cè)赼中調(diào)用foo就不會(huì)有問(wèn)題了:
In [85]: a.foo(1) 2
我們也可以試試調(diào)用A.foo:
In [86]: A.foo(a, 1) 2
總結(jié)
python的類中定義函數(shù)時(shí)的self關(guān)鍵字跟python的方法函數(shù)有關(guān),方法函數(shù)由類的實(shí)例化對(duì)象調(diào)用,需要把調(diào)用它的實(shí)例化對(duì)象傳入方法函數(shù)中,self即是表示實(shí)例化對(duì)象的形參。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Pytorch創(chuàng)建隨機(jī)值張量的過(guò)程詳解
這篇文章主要介紹了Pytorch創(chuàng)建隨機(jī)值張量的過(guò)程詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09導(dǎo)入tensorflow時(shí)報(bào)錯(cuò):cannot import name ''abs''的解決
這篇文章主要介紹了導(dǎo)入tensorflow時(shí)報(bào)錯(cuò):cannot import name 'abs'的解決,文中介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Python Numpy教程之排序,搜索和計(jì)數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了Python?NumPy中排序,搜索和計(jì)數(shù)的實(shí)現(xiàn),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定幫助,需要的可以參考一下2022-08-08對(duì)python中l(wèi)ist的五種查找方法說(shuō)明
這篇文章主要介紹了對(duì)python中l(wèi)ist的五種查找方法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07python實(shí)現(xiàn)兩個(gè)dict合并與計(jì)算操作示例
這篇文章主要介紹了python實(shí)現(xiàn)兩個(gè)dict合并與計(jì)算操作,結(jié)合具體實(shí)例形式分析了Python使用collections.Counter進(jìn)行字典dict合并與遍歷輸出相關(guān)操作技巧,需要的朋友可以參考下2019-07-07Python刪除Java源文件中全部注釋的實(shí)現(xiàn)方法
這篇文章主要介紹了Python刪除Java源文件中全部注釋的實(shí)現(xiàn)方法,涉及Python讀取文件、正則匹配、字符串查找、替換等相關(guān)操作技巧,需要的朋友可以參考下2017-08-08python如何繪制登陸時(shí)的衛(wèi)星云圖(TBB)
這篇文章主要介紹了python如何繪制登陸時(shí)的衛(wèi)星云圖(TBB),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Python facenet進(jìn)行人臉識(shí)別測(cè)試過(guò)程解析
這篇文章主要介紹了Python facenet進(jìn)行人臉識(shí)別測(cè)試過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08