1. 程式人生 > >Python中self的含義到底是什麼?

Python中self的含義到底是什麼?

注:本文為轉載,如有侵權,請告知將予以刪除

原文連結:https://blog.csdn.net/xjl85/article/details/76083238

 

 

先來看一個例子:

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

t = Test()
t.prt()

輸出結果:

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

可以看出,self代表的是類的例項。而self.class則指向類。

當然,self不必非寫成self,也可以寫成this…等等,執行結果是一樣的。但是按照python 的約定俗成的慣例,還是寫成self比較好。

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

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

t = Test()
Test.prt(t)

執行結果:

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

但self在定義時不可以省略。

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

t = Test()
t.prt()

執行結果報錯:

TypeError: prt() takes 0 positional arguments but 1 was given

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

在繼承時,傳入的是哪個例項,就是那個傳入的例項,而不是指定義了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 0x0057C3F0>
<__main__.Child object at 0x0057C3F0>
<__main__.Parent object at 0x0057CBD0>

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

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

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

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

執行結果:

self in Test: <__main__.Test object at 0x0045C3B0>
self in Desc: <__main__.Desc object at 0x0045C310> 
<__main__.Desc object at 0x0045C310> <__main__.Test object at 0x0045C3B0> <class '__main__.Test'>

最後一句t.x,也就是Test類的例項t的屬性x,由於例項t中並沒有定義屬性x,所以找到了類屬性x,而該屬性是描述符屬性,為Desc類的例項而已,所以此處並沒有頂用Test的任何方法。

而如果把t.x改為Test.x

執行結果:

self in Test: <__main__.Test object at 0x0044C3B0>
self in Desc: <__main__.Desc object at 0x0044C310> 
<__main__.Desc object at 0x0044C310> None <class '__main__.Test'>

由於在很多時候描述符類中仍然需要知道呼叫該描述符的例項是誰,所以在描述符類中存在第二個引數ins,用來表示呼叫它的類例項,所以t.x時可以看到第三行中的執行結果中第二項為

<<main.Test object at 0x0000000002A570B8>

而採用Test.x進行呼叫時,由於沒有例項,所以返回None。