搜尋
首頁後端開發Python教學理解Python中self的用法

剛開始學習Python的類別寫法的時候覺得很是麻煩,為什麼定義時需要而調用時又不需要,為什麼不能內部簡化從而減少我們敲擊鍵盤的次數?你看完這篇文章後就會明白所有的疑問。

self代表類別的實例,而非類別。

實例來說明:

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

#執行結果如下

##

<__main__.Test object at 0x000000000284E080>
<class &#39;__main__.Test&#39;>

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

self不必非寫成self

有很多童鞋是先學習別的語言然後學習Python的,所以總覺得self怪怪的,想寫成this,可以嗎?

當然可以,還是把上面的程式碼改寫一下。

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

改成this後,運行結果完全一樣。

當然,最好還是尊重約定俗成的習慣,使用self。

self可以不寫嗎

在Python的解釋器內部,當我們呼叫t.prt()時,實際上Python解釋成Test.prt(t ),也就是說把self替換成類別的實例。

有興趣的童鞋可以把上面的t.prt()一行改寫一下,運行後的實際結果完全相同。

其實已經部分說明了self在定義時不可以省略,如果非要試一下,那麼請看下面:

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

運行時提醒錯誤如下:prt在定義時沒有參數,但我們運行時強行傳了一個參數。

由於上面解釋過了t.prt()等同於Test.prt(t),所以程式提醒我們多傳了一個參數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

當然,如果我們的定義和呼叫時均不傳類別實例是可以的,這就是類別方法。

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

運行結果如下

<class &#39;__main__.Test&#39;>

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

先看程式碼

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()

運行結果如下

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

解釋:

執行c.cprt()時應該沒有理解問題,指的是Child類別的實例。

但是在執行c.pprt()時,等同於Child.pprt(c),所以self指的依然是Child類別的實例,由於self中沒有定義pprt()方法,所以沿著繼承樹往上找,發現在父類別Parent中定義了pprt()方法,所以就會成功呼叫。

在描述符類別中,self指的是描述符類別的實例

#不太容易理解,先看實例:

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

運行結果如下:

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 &#39;__main__.Test&#39;>

大部分童鞋開始有疑問了,為什麼在Desc類中定義的self不是應該是呼叫它的實例t嗎?怎麼變成了Desc類別的實例了呢?

注意:這裡需要睜大眼睛看清楚了,這裡呼叫的是t.x,也就是說是Test類別的實例t的屬性x,由於實例t中並沒有定義屬性x,所以找到了類別屬性x,而該屬性是描述符屬性,為Desc類別的實例而已,所以此處並沒有頂用Test的任何方法。

那麼我們如果直接透過類別來呼叫屬性x也可以得到相同的結果。

下面是把t.x改為Test.x運行的結果。

self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class &#39;__main__.Test&#39;>

題外話:由於很多時候描述符類別中仍然需要知道呼叫該描述符的實例是誰,所以在描述符類別中存在第二個參數ins,用來表示呼叫它的類別實例,所以t.x時可以看到第三行中的運行結果中第二項為。而採用Test.x進行呼叫時,由於沒有實例,所以回傳None。

從OO的本質理解python中的self

舉個栗子,假設我要對使用者的資料進行操作,使用者的資料包含name和age。如果用面向過程的話,實現出來是下面這樣子的。

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

可以看到,對使用者的各種操作,都要傳user參數進去。

如果用物件導向的話,就不用每次把user參數傳來傳去,把相關的資料和操作綁定在一個地方,在這個類別的各個地方,可以方便的取得資料。

之所以可以在類別中的各個地方存取數據,本質就是綁定了self這個東西,它方法的第一個參數,當然可以不叫self,叫其它名字,self只不過是個約定。
下面是物件導向的實現,可以看到,結構化多了,清晰可讀。

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(&#39;kzc&#39;,17) 
print u.GetName() 
print u.GetAge()

從上面這個例子可以看出,其實物件導向挺有用的,只不過大多數人抽象的不好,封裝的不好,錯誤的運用。

總結

    self在定義時需要定義,但在呼叫時會自動傳入。
  • self的名字並不是規定死的,但是最好還是按照約定是用self
  • self總是指呼叫時的類別的實例。

更多理解Python中self的用法相關文章請關注PHP中文網!


#
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs.C:申請和用例Python vs.C:申請和用例Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

2小時的Python計劃:一種現實的方法2小時的Python計劃:一種現實的方法Apr 11, 2025 am 12:04 AM

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python:探索其主要應用程序Python:探索其主要應用程序Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

您可以在2小時內學到多少python?您可以在2小時內學到多少python?Apr 09, 2025 pm 04:33 PM

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?Apr 02, 2025 am 07:18 AM

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python 3.6加載Pickle文件報錯"__builtin__"模塊未找到怎麼辦?Python 3.6加載Pickle文件報錯"__builtin__"模塊未找到怎麼辦?Apr 02, 2025 am 07:12 AM

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何提高jieba分詞在景區評論分析中的準確性?如何提高jieba分詞在景區評論分析中的準確性?Apr 02, 2025 am 07:09 AM

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境