欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

全面理解Python中self的用法

 更新時間:2016年06月04日 11:56:09   作者:mattkang  
Python中看到或使用self時一定要弄明白self的指代,這里就帶大家來全面理解Python中self的用法,需要的朋友可以參考下

剛開始學(xué)習(xí)Python的類寫法的時候覺得很是麻煩,為什么定義時需要而調(diào)用時又不需要,為什么不能內(nèi)部簡化從而減少我們敲擊鍵盤的次數(shù)?你看完這篇文章后就會明白所有的疑問。

self代表類的實(shí)例,而非類。

實(shí)例來說明:

class Test:
  def prt(self):
    print(self)
    print(self.__class__)
 
t = Test()
t.prt()

執(zhí)行結(jié)果如下

<__main__.Test object at 0x000000000284E080>
<class '__main__.Test'>

從上面的例子中可以很明顯的看出,self代表的是類的實(shí)例。而self.class則指向類。

self不必非寫成self

有很多童鞋是先學(xué)習(xí)別的語言然后學(xué)習(xí)Python的,所以總覺得self怪怪的,想寫成this,可以嗎?

當(dāng)然可以,還是把上面的代碼改寫一下。

class Test:
  def prt(this):
    print(this)
    print(this.__class__)
 
t = Test()
t.prt()

改成this后,運(yùn)行結(jié)果完全一樣。

當(dāng)然,最好還是尊重約定俗成的習(xí)慣,使用self。

self可以不寫嗎

在Python的解釋器內(nèi)部,當(dāng)我們調(diào)用t.prt()時,實(shí)際上Python解釋成Test.prt(t),也就是說把self替換成類的實(shí)例。

有興趣的童鞋可以把上面的t.prt()一行改寫一下,運(yùn)行后的實(shí)際結(jié)果完全相同。

實(shí)際上已經(jīng)部分說明了self在定義時不可以省略,如果非要試一下,那么請看下面:

class Test:
  def prt():
    print(self)
 
t = Test()
t.prt()

運(yùn)行時提醒錯誤如下:prt在定義時沒有參數(shù),但是我們運(yùn)行時強(qiáng)行傳了一個參數(shù)。

由于上面解釋過了t.prt()等同于Test.prt(t),所以程序提醒我們多傳了一個參數(shù)t。

Traceback (most recent call last):
 File "h.py", line 6, in <module>
  t.prt()
TypeError: prt() takes 0 positional arguments but 1 was given

當(dāng)然,如果我們的定義和調(diào)用時均不傳類實(shí)例是可以的,這就是類方法。

class Test:
  def prt():
    print(__class__)
Test.prt()

運(yùn)行結(jié)果如下

<class '__main__.Test'>

在繼承時,傳入的是哪個實(shí)例,就是那個傳入的實(shí)例,而不是指定義了self的類的實(shí)例。

先看代碼

class Parent:
  def pprt(self):
    print(self)
 
class Child(Parent):
  def cprt(self):
    print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()

運(yùn)行結(jié)果如下

<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>

解釋:

運(yùn)行c.cprt()時應(yīng)該沒有理解問題,指的是Child類的實(shí)例。

但是在運(yùn)行c.pprt()時,等同于Child.pprt(c),所以self指的依然是Child類的實(shí)例,由于self中沒有定義pprt()方法,所以沿著繼承樹往上找,發(fā)現(xiàn)在父類Parent中定義了pprt()方法,所以就會成功調(diào)用。

在描述符類中,self指的是描述符類的實(shí)例

不太容易理解,先看實(shí)例:

class Desc:
  def __get__(self, ins, cls):
    print('self in Desc: %s ' % self )
    print(self, ins, cls)
class Test:
  x = Desc()
  def prt(self):
    print('self in Test: %s' % self)
t = Test()
t.prt()
t.x

運(yùn)行結(jié)果如下:

self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8> <class '__main__.Test'>

大部分童鞋開始有疑問了,為什么在Desc類中定義的self不是應(yīng)該是調(diào)用它的實(shí)例t嗎?怎么變成了Desc類的實(shí)例了呢?

注意:此處需要睜大眼睛看清楚了,這里調(diào)用的是t.x,也就是說是Test類的實(shí)例t的屬性x,由于實(shí)例t中并沒有定義屬性x,所以找到了類屬性x,而該屬性是描述符屬性,為Desc類的實(shí)例而已,所以此處并沒有頂用Test的任何方法。

那么我們?nèi)绻苯油ㄟ^類來調(diào)用屬性x也可以得到相同的結(jié)果。

下面是把t.x改為Test.x運(yùn)行的結(jié)果。

self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class '__main__.Test'>

題外話:由于在很多時候描述符類中仍然需要知道調(diào)用該描述符的實(shí)例是誰,所以在描述符類中存在第二個參數(shù)ins,用來表示調(diào)用它的類實(shí)例,所以t.x時可以看到第三行中的運(yùn)行結(jié)果中第二項(xiàng)為<main.Test object at 0x0000000002A570B8>。而采用Test.x進(jìn)行調(diào)用時,由于沒有實(shí)例,所以返回None。

從OO的本質(zhì)理解python中的self
舉個栗子,假設(shè)我要對用戶的數(shù)據(jù)進(jìn)行操作,用戶的數(shù)據(jù)包含name和age。如果用面向過程的話,實(shí)現(xiàn)出來是下面這樣子的。

def user_init(user,name,age): 
  user['name'] = name 
  user['age'] = age 
 
def set_user_name(user, x): 
  user['name'] = x 
 
def set_user_age(user, x): 
  user['age'] = x 
 
def get_user_name(user): 
  return user['name'] 
 
def get_user_age(user): 
  return user['age'] 
 
myself = {} 
user_init(myself,'kzc',17) 
print get_user_age(myself) 
set_user_age(myself,20) 
print get_user_age(myself) 

可以看到,對用戶的各種操作,都要傳user參數(shù)進(jìn)去。
如果用面向?qū)ο蟮脑挘筒挥妹看伟製ser參數(shù)傳來傳去,把相關(guān)的數(shù)據(jù)和操作綁定在一個地方,在這個類的各個地方,可以方便的獲取數(shù)據(jù)。
之所以可以在類中的各個地方訪問數(shù)據(jù),本質(zhì)就是綁定了self這個東西,它方法的第一個參數(shù),當(dāng)然可以不叫self,叫其它名字,self只不過是個約定。
下面是面向?qū)ο蟮膶?shí)現(xiàn),可以看到,結(jié)構(gòu)化多了,清晰可讀。

class User(object): 
  def __init__(self,name,age): 
    self.name = name 
    self.age = age 
 
  def SetName(self,name): 
    self.name = name 
 
  def SetAge(self,age): 
    self.age = age 
 
  def GetName(self): 
    return self.name 
 
  def GetAge(self): 
    return self.age 
 
u = User('kzc',17) 
print u.GetName() 
print u.GetAge() 

從上面這個例子可以看出,其實(shí)面向?qū)ο笸τ杏玫?,只不過大多數(shù)人抽象的不好,封裝的不好,錯誤的運(yùn)用。

總結(jié)

  • self在定義時需要定義,但是在調(diào)用時會自動傳入。
  • self的名字并不是規(guī)定死的,但是最好還是按照約定是用self
  • self總是指調(diào)用時的類的實(shí)例。

相關(guān)文章

  • Python存儲或讀取json時如何引入額外的雙引號和轉(zhuǎn)義引號

    Python存儲或讀取json時如何引入額外的雙引號和轉(zhuǎn)義引號

    這篇文章主要介紹了Python存儲或讀取json時如何引入額外的雙引號和轉(zhuǎn)義引號問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python的字符串示例講解

    Python的字符串示例講解

    本文重點(diǎn)講解字符串的創(chuàng)建,字符串的定義和字符串的常見操作,對Python的字符串不熟悉的同學(xué)隨小編一起學(xué)習(xí)吧!
    2021-04-04
  • Python帶動態(tài)參數(shù)功能的sqlite工具類

    Python帶動態(tài)參數(shù)功能的sqlite工具類

    這篇文章主要介紹了Python帶動態(tài)參數(shù)功能的sqlite工具類,涉及Python針對sqlite數(shù)據(jù)庫的連接、查詢、sql語句執(zhí)行等相關(guān)操作封裝與使用技巧,需要的朋友可以參考下
    2018-05-05
  • Python報(bào)錯:ModuleNotFoundError的解決辦法

    Python報(bào)錯:ModuleNotFoundError的解決辦法

    "ModuleNotFoundError: No module named 'xxx'"這個報(bào)錯是個非常常見的報(bào)錯,幾乎每個python程序員都遇到過,下面這篇文章主要給大家介紹了關(guān)于Python報(bào):ModuleNotFoundError錯誤的解決辦法,需要的朋友可以參考下
    2022-06-06
  • python-docx文件定位讀取過程(嘗試替換)

    python-docx文件定位讀取過程(嘗試替換)

    今天小編就為大家分享一篇python-docx文件定位讀取過程(嘗試替換),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • python 的賦值語句和基本輸入輸出詳解

    python 的賦值語句和基本輸入輸出詳解

    這篇文章主要為大家介紹了python 賦值語句和基本輸入輸出,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • Python?生成多行重復(fù)數(shù)據(jù)的方法實(shí)現(xiàn)

    Python?生成多行重復(fù)數(shù)據(jù)的方法實(shí)現(xiàn)

    本文主要介紹了Python?生成多行重復(fù)數(shù)據(jù)的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • python字符串拼接.join()和拆分.split()詳解

    python字符串拼接.join()和拆分.split()詳解

    這篇文章主要為大家介紹了python字符串拼接.join()和拆分.split(),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • Python基于Twilio及騰訊云實(shí)現(xiàn)國際國內(nèi)短信接口

    Python基于Twilio及騰訊云實(shí)現(xiàn)國際國內(nèi)短信接口

    這篇文章主要介紹了Python基于Twilio及騰訊云實(shí)現(xiàn)國際國內(nèi)短信接口,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • 教你怎么用Python selenium操作瀏覽器對象的基礎(chǔ)API

    教你怎么用Python selenium操作瀏覽器對象的基礎(chǔ)API

    今天給大家?guī)淼氖顷P(guān)于Python的相關(guān)知識,文章圍繞著怎么用Python selenium操作瀏覽器對象的基礎(chǔ)API展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評論