搜尋
首頁後端開發Python教學Python中的self怎麼使用

在介紹Python的self用法之前,先來介紹下Python中的類別和實例
我們知道,物件導向最重要的概念就是類別(class)和實例(instance),類別是抽象的模板,例如學生這個抽象的事物,可以用一個Student類別來表示。而實例是根據類別創建出來的一個個具體的“物件”,每個物件都從類別中繼承有相同的方法,但各自的資料可能不同。
1、以Student類別為例,在Python中,定義類別如下:

class Student(object):
    pass

(Object)表示該類別從哪個類別繼承下來的,Object類別是所有類別都會繼承的類別。

2、實例:定義好了類,就可以透過Student類別建立出Student的實例,建立實例是透過類別名稱()實作:

student = Student()

3、因為類別起到模板的作用,因此,可以在創建實例的時候,把我們認為必須綁定的屬性強制填寫進去。這裡就用到Python當中的一個內建方法__init__方法,例如在Student類別時,把name、score等屬性綁上去:

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

這裡注意:(1)、__init__方法的第一參數永遠是self,表示創建的類別實例本身,因此,在__init__方法內部,就可以把各種屬性綁定到self,因為self就指向創建的實例本身。 (2)、有了__init__方法,在創建實例的時候,就不能傳入空的參數了,必須傳入與__init__方法匹配的參數,但self不需要傳,Python解釋器會自己把實例變數傳進去:

>>>student = Student("Hugh", 99)
>>>student.name
"Hugh"
>>>student.score
99

另外,這裡self就是指類別本身,self.name就是Student類別的屬性變量,就是Student類別所有。而name是外部傳來的參數,不是Student類別所自帶的。故,self.name = name的意思就是把外部傳來的參數name的值賦值給Student類別自己的屬性變數self.name

4、和普通數相比,在類別中定義函數只有一點不同,就是第一參數永遠是類別的本身實例變數self ,並且在呼叫時,不用傳遞該參數。除此之外,類別的方法(函數)和普通函數沒啥區別,你既可以用預設參數、可變參數或關鍵字參數*args是可變參數,args接收的是一個tuple**kw是關鍵字參數,kw接收的是一個dict)。

5、既然Student類別實例本身就擁有這些數據,那麼要存取這些數據,就沒必要從外面的函數去訪問,而可以直接在Student類別的內部定義訪問資料的函數(方法),這樣,就可以把」資料」封裝起來。這些封裝資料的函數是和Student類別本身是關聯起來的,稱為類別的方法:

class Student(obiect):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def print_score(self):
        print "%s: %s" % (self.name, self.score)
>>>student = Student("Hugh", 99)
>>>student.print_score
Hugh: 99

這樣一來,我們從外部看Student類,就只需要知道,創建實例需要給出name和score。而如何列印,都是在Student類別的內部定義的,這些資料和邏輯被封裝起來了,呼叫很容易,但卻不知道內部實作的細節。

如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個底線,在Python中,實例的變數名稱如果以開頭,就變成了一個私有變數(private),只有內部可以訪問,外部不能訪問,所以,我們把Student類別改一改:

class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score
    def print_score(self):
        print "%s: %s" %(self.__name,self.__score)

改完後,對於外部程式碼來說,沒什麼變動,但是已經無法從外部存取實例變數.__name和實例變數.__score了:

>>> student = Student('Hugh', 99)
>>> student.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: &#39;Student&#39; object has no attribute &#39;__name&#39;

這樣就確保了外部程式碼不能隨意修改物件內部的狀態,這樣透過存取限制的保護,程式碼更加健壯。

但是如果外部程式碼要取得name和score怎麼辦?可以為Student類別增加get_name和get_score這樣的方法:

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

如果又要允許外部程式碼修改score怎麼辦?可以增加Student類別set_score方法:

class Student(object):
    ...

    def set_score(self, score):
        self.__score = score

要注意的是,在Python中,變數名稱類似__xxx__的,也就是以雙底線開頭,並且以雙底線結尾的,是特殊變量,特殊變數是可以直接存取的,不是private變量,所以,不能用__name____score__這樣的變數名。

有些時候,你會看到以一個底線開頭的實例變數名,例如_name,這樣的實例變數外部是可以存取的,但是,按照約定俗成的規定,當你看到這樣的變數時,意思是,「雖然我可以被訪問,但是,請把我視為私有變量,不要隨意訪問」。

封裝的另一個好處是可以隨時為Student類別增加新的方法,例如:get_grade:

class Student(object):
    ...
    def get_grade(self):
        if self.score >= 90:
            return &#39;A&#39;
        elif self.score >= 60:
            return &#39;B&#39;
        else:
            return &#39;C&#39;

同樣的,get_grade方法可以直接在實例變數上調用,不需要知道內部實作細節:

>>> student.get_grade()
&#39;A&#39;

6、self的仔细用法
(1)、self代表类的实例,而非类。

class Test:
    def ppr(self):
        print(self)
        print(self.__class__)

t = Test()
t.ppr()
执行结果:
<__main__.Test object at 0x000000000284E080>
<class &#39;__main__.Test&#39;>

从上面的例子中可以很明显的看出,self代表的是类的实例。而self.__class__则指向类。
注意:把self换成this,结果也一样,但Python中最好用约定俗成的self。
(2)、self可以不写吗?
在Python解释器的内部,当我们调用t.ppr()时,实际上Python解释成Test.ppr(t),也就是把self替换成了类的实例。

class Test:
    def ppr():
        print(self)

t = Test()
t.ppr()

运行结果如下:

Traceback (most recent call last):
  File "cl.py", line 6, in
    t.ppr()
TypeError: ppr() takes 0 positional arguments but 1 was given

运行时提醒错误如下:ppr在定义时没有参数,但是我们运行时强行传了一个参数。

由于上面解释过了t.ppr()等同于Test.ppr(t),所以程序提醒我们多传了一个参数t。

这里实际上已经部分说明了self在定义时不可以省略。

当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法。

class Test:
    def ppr():
        print(__class__)

Test.ppr()

运行结果:
<class &#39;__main__.Test&#39;>

(3)、在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了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>
<__main__.child object at>
<__main__.parent object at>

解释:
运行c.cprt()时应该没有理解问题,指的是Child类的实例。
但是在运行c.pprt()时,等同于Child.pprt(c),所以self指的依然是Child类的实例,由于self中没有定义pprt()方法,所以沿着继承树往上找,发现在父类Parent中定义了pprt()方法,所以就会成功调用。

(4)、在描述符类中,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>
self in Desc: <__main__.desc object at>
<__main__.desc object at> <__main__.test object at>

这里主要的疑问应该在: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;>

以上是Python中的self怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
Python:遊戲,Guis等Python:遊戲,Guis等Apr 13, 2025 am 12:14 AM

Python在遊戲和GUI開發中表現出色。 1)遊戲開發使用Pygame,提供繪圖、音頻等功能,適合創建2D遊戲。 2)GUI開發可選擇Tkinter或PyQt,Tkinter簡單易用,PyQt功能豐富,適合專業開發。

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...

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尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

mPDF

mPDF

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