class Box(object):
def __init__(this, boxname, size, color):
this.boxname = boxname
this.size = size
this.color = color # self就是用於存儲對象屬性的集合,就算沒有屬性self也是必備的,代表類的實例,而非類。
def open(this, myself):
print('-->用自己的myself,打開那個%s,%s的%s' % (myself.color, myself.__dict__['size'], myself.boxname))
print('-->用類自己的self,打開那個%s,%s的%s' % (this.__dict__['color'], this.__dict__['size'], this.boxname))
@classmethod
def close(cls):
print('-->關閉%s,謝謝' )
b = Box('魔盒', '14m', '紅色')
Box.close() # close是一個類方法,可以通過類調用
b.close()# close是一個類方法,自然也可以通過實例調用
b.open(b) # 當我們調用b.open(b)時,實際上Python解釋成Box.open(b,b),也就是把self替換成了類的實例b, 另外myself也是一個實例,所以相當於兩個輸入實例參數。
Box.open(b,b)#上面方法實際執行就是這樣的,當我們調用b.open(b)時,實際上Python解釋成Box.open(b,b)。
print(b.__dict__) # 這裏返回的就是self本身,self存儲屬性,沒有動作。
self
的仔細用法。
(1)、self代表類的實例,而非類。
class Test:
def ppr(self):
print(self)
print(self.__class__)
t = Test()
t.ppr()
執行結果:
<__main__.Test object at 0x000000000284E080>
<class '__main__.Test'>
從上面的例子中可以很明顯的看出,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 <module>
t.ppr()
TypeError: ppr() takes 0 positional arguments but 1 was given
運行時提醒錯誤如下:ppr在定義時沒有參數,但是我們運行時強行傳了一個參數。
由於上面解釋過了t.ppr()等同於Test.ppr(t),所以程序提醒我們多傳了一個參數t。
這裏實際上已經部分說明了self
在定義時不可以省略。
當然,如果我們的定義和調用時均不傳類實例是可以的,這就是類方法。
class Test:
@classmethod
def ppr(cls):
print(__class__)
Test.ppr()
運行結果:
<class '__main__.Test'>
(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 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()方法,所以就會成功調用。
(4)、在描述符類中,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 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8> <class '__main__.Test'>
這裏主要的疑問應該在: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 '__main__.Test'>
總結:以上是之前學習Python時的小結,現在已博客方式呈現,同時爲pyspark中調用self遇到的問題做鋪墊,後面也會對比java,未完待續…….
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
</div>