天天看點

python 函數參數self_Python 類self 詳解

Python 中的self是學習類的一個難點,很多初學者學到Python self的時候,都會出現難以了解的情況,下面,蝸牛部落格就為您進行講解一下Python中的self。

Updated on Nov-02-2018:

一、首先要明确幾個概念:

1. self代表類的執行個體,而非類。

例:

class Person:

def pri(self):

print(self)

a = Person()

a.pri()

print(id(a))

運作結果:

<__main__.Person object at0x04B37A90>

78871184

将0x04B37A90轉換成十進制為78871184,與self的id相同,說明在這裡self代表的是執行個體a的id位址。

下面這個例子其實更好:

首先定義一個函數:

class TestSelf:

def self_id(self):

return self # 傳回self自身

t1 = TestSelf() # 執行個體化為一個對象t1

print(t1) # 列印t1對象自身,

print(t1.self_id()) # 列印t1對象的self_id方法的傳回值

# 輸出

# <__main__.TestSelf object at 0x1055afbe0>

# <__main__.TestSelf object at 0x1055afbe0>

print(t1 is t1.self_id()) # 使用is判斷他們的指向是否一緻

# 輸出

# True

那麼我們就可以看到有這樣的寫法;

class MainEngine:

"""

"""

def add_engine(self, engine_class: Any):

"""

Add function engine.

"""

engine = engine_class(self, self.event_engine)

self.engines[engine.engine_name] = engine

其中的engine = engine_class(self, self.event_engine)相當于engine = engine_class(mainEngine(), self.event_engine)

2. self可以不寫嗎

(1)編寫類中的函數時,不寫self會報錯。

例:如下面這個最簡單的類可以正常運作的,如果删除def prt(self)中的self,就會報“TypeError: enten88() takes no arguments (1 given)”的錯誤。

class Test(object):

def prt():

print("this is test")

b = Test()

b.prt()

這其實與class中函數調用的方式有關,在給出一個執行個體以後,我們調用類中的具體方法(即函數)時,預設傳入了self參數(即執行個體位址),如上面的執行個體,我們在定義函數時沒有給他形參,那麼調用時自動傳入的第一個參數self無處容納,即參數多餘,報錯。

(2)沒有self可以運作

下面的代碼其實是可以運作的。因為這裡沒有調用執行個體,沒有self傳入,那麼也就不向pri傳遞參數了(特例)。

class Person:

def pri():

print('test successfully')

Person.pri()

上面是python3的版本,但是在python2.x下面

class Person(object):

def pri():

print 'test successfully'

Person.pri()

會報錯:

Traceback (most recent call last):

File "test.py", line 59, in

Person.pri()

TypeError: unbound method pri() must be called with Person instance as first arg

ument (got nothing instead)

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()方法,是以就會成功調用。

更多知識可以看這裡:http://python.jobbole.com/81921/

二、self與變量

class Test(object):

quip = "This is a test!"

def prt(self):

print quip

b = Test()

b.prt()

會報錯:

python 函數參數self_Python 類self 詳解

這時,隻需要将

print quip

改成:

print self.quip

或者

print Test.quip

就可以正常顯示結果了。

三、self必須是self嗎?

我們先看一個标準類的寫法:

class Song():

def __init__(self,lyrics):

self.lyric = lyrics

def sing_me_a_song(self):

for line in self.lyric:

print line

happy_baby = Song(['happy birthday to you',

'I do not want to get sued',

'So i will stop right there'])

bulls_on_parade = Song(['They rally around the family',

'with pockets full of shells'])

happy_baby.sing_me_a_song()

bulls_on_parade.sing_me_a_song()

運作結果如下:

python 函數參數self_Python 類self 詳解

說明:在代碼:

self.lyric = lyrics

中,等号左邊的那個lyric是執行個體的屬性,後面那個lyric是方法__init__的參數,兩個是不同的

然後,我将将代碼改成如下的形式:

class Song():

def __init__(me,lyrics):

me.a = lyrics

def sing_me_a_song(me):

for line in me.a:

print line

happy_baby = Song(['happy birthday to you',

'I do not want to get sued',

'So i will stop right there'])

bulls_on_parade = Song(['They rally around the family',

'with pockets full of shells'])

happy_baby.sing_me_a_song()

bulls_on_parade.sing_me_a_song()

程式照樣能運作,且運作的結果一模一樣。

那麼,我們可不可以不用這個self(或者其他名稱),比如将代碼中的

self.lyric = lyrics

直接改成呢?

lyric = lyrics

您可以自己試一試,答案是不行的,這樣等于定義了一個全局的變量。

是以我們可以得出如下的結論:

Self是必須的,但是名稱不一定必須是self,你可以改成做任意的其他名字,不過在一個類中,定義所有的函數時都必須統一用這一個名字,比如上面的例子中,要麼統一用self,要麼統一用me,不能在一個類中,又有self,又有me。