Python中self的含義到底是什麼?
阿新 • • 發佈:2018-12-28
注:本文為轉載,如有侵權,請告知將予以刪除
原文連結: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。