首頁 >後端開發 >Python教學 >python物件導向方法的區別

python物件導向方法的區別

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼原創
2019-06-24 13:49:162907瀏覽

Python從設計之初就已經是一門物件導向的語言,也因為如此,在Python中創建一個類別和物件是很容易的。

方法包括:實例方法、靜態方法和類別方法,三種方法在記憶體中都歸屬於類,差別在於呼叫方式不同。

實例方法:由物件呼叫;至少一個self參數;執行普通方法時,自動將呼叫該方法的物件賦值給self;

類別方法:由類別呼叫; 至少一個cls參數;執行類別方法時,自動將呼叫該方法的類別複製給cls;

靜態方法:由類別呼叫;無預設參數。

python物件導向方法的區別

實例方法

class Kls(object):
    def __init__(self, data):
        self.data = data
    def printd(self):
        print(self.data)
ik1 = Kls('leo')
ik2 = Kls('lee')
ik1.printd()
ik2.printd()

輸出:

leo 
lee

在上述範例中,printd為實例方法。實例方法第一個參數為self,當使用ik1.printd()呼叫實例方法時,實例ik1會傳遞給self參數,這樣self參數就可以引用目前正在呼叫實例方法的實例。利用實例方法的這個特性,上述程式碼正確輸出了兩個實例的成員資料。

相關推薦:《Python影片教學

#類別方法

Python 的類別方法採用裝飾器@classmethod來定義,我們直接看例子。

class Kls(object):
    num_inst = 0
    def __init__(self):
        Kls.num_inst = Kls.num_inst + 1
    @classmethod
    def get_no_of_instance(cls):
        return cls.num_inst
ik1 = Kls()
ik2 = Kls()
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()

輸出:

2 
2

在上述例子中,我們需要統計類別Kls實例的個數,因此定義了一個類別變數num_inst來存放實例個數。透過裝飾器@classmethod的使用,方法get_no_of_instance被定義成一個類別方法。在呼叫類別方法時,Python 會將類別(class Kls)傳遞給cls,這樣在get_no_of_instance內部就可以引用類別變數num_inst。 

由於在呼叫類別方法時,只需要將類型本身傳遞給類別方法,因此,既可以透過類別也可以透過實例來呼叫類別方法。

靜態方法

在開發中,我們常常需要定義一些方法,這些方法跟類別有關,但在實作時並不需要引用類別或實例,例如,設定環境變量,修改另一個類別的變量,等。這個時候,我們可以使用靜態方法。 

Python 使用裝飾器@staticmethod定義靜態方法。

IND = 'ON'

class Kls(object):
    def __init__(self, data):
        self.data = data
    @staticmethod
    def checkind():
        return IND == 'ON'
    def do_reset(self):
        if self.checkind():
            print('Reset done for: %s' % self.data)
    def set_db(self):
        if self.checkind():
            print('DB connection made for: %s' % self.data)
ik1 = Kls(24)
ik1.do_reset()
ik1.set_db()

輸出:

Reset done for: 24 
DB connection made for: 24

在程式碼中,我們定義了一個全域變數IND,由於IND跟類別Kls相關,所以我們將方法checkind放置在類別Kls中定義。方法checkind只需檢查IND的值,而不需要引用類別或實例,因此,我們將方法checkind定義為靜態方法。 

對於靜態方法,Python 並不需要傳遞類別或實例,因此,可以使用類別也可以使用實例來呼叫靜態方法。

實例方法,類別方法與靜態方法的差異

我們用程式碼說明實例方法,類別方法,靜態方法的差異。注意下述程式碼中方法foo,class_foo,static_foo的定義以及使用。

class Kls(object):
    def foo(self, x):
        print('executing foo(%s,%s)' % (self, x))
    @classmethod
    def class_foo(cls,x):
        print('executing class_foo(%s,%s)' % (cls,x))
    @staticmethod
    def static_foo(x):
        print('executing static_foo(%s)' % x)
ik = Kls()
# 实例方法
ik.foo(1)
print(ik.foo)
print('==========================================')
# 类方法
ik.class_foo(1)
Kls.class_foo(1)
print(ik.class_foo)
print('==========================================')
# 静态方法
ik.static_foo(1)
Kls.static_foo('hi')
print(ik.static_foo)

輸出:

executing foo(<__main__.Kls object at 0x0551E190>,1)
<bound method Kls.foo of <__main__.Kls object at 0x0551E190>>
==========================================
executing class_foo(<class &#39;__main__.Kls&#39;>,1)
executing class_foo(<class &#39;__main__.Kls&#39;>,1)
<bound method type.class_foo of <class &#39;__main__.Kls&#39;>>
==========================================
executing static_foo(1)
executing static_foo(hi)
<function static_foo at 0x055238B0>

對於實例方法,呼叫時會把實例ik當作第一個參數傳遞給self參數。因此,在呼叫ik.foo(1)時輸出了實例ik的位址。

對於類別方法,呼叫時會把類別Kls當作第一個參數傳遞給cls參數。因此,當呼叫ik.class_foo(1)時輸出了Kls類型資訊。 

前面提到,可以透過類別也可以透過實例來呼叫類別方法,在上述程式碼中,我們再一次進行了驗證。

對於靜態方法,呼叫時並不需要傳遞類別或實例。其實,靜態方法很像我們在類別外定義的函數,只不過靜態方法可以透過類別或實例來呼叫而已。

值得注意的是,在上述例子中,foo只是個函數,但當呼叫ik.foo的時候我們得到的是一個已經跟實例ik綁定的函數。呼叫foo時需要兩個參數,但呼叫ik.foo時只需要一個參數。 foo跟ik進行了綁定,因此,當我們印出ik.foo時,會看到以下輸出:

<bound method Kls.foo of <__main__.Kls object at 0x0551E190>>

當呼叫ik.class_foo時,由於class_foo是類別方法,因此,class_foo跟Kls進行了綁定(而不是跟ik綁定)。當我們列印ik.class_foo時,輸出:

<bound method type.class_foo of <class &#39;__main__.Kls&#39;>>

當呼叫ik.static_foo時,靜態方法並不會與類別或實例綁定,因此,列印ik.static_foo(或Kls.static_foo)時輸出:

<function static_foo at 0x055238B0>

概括來說,是否與類別或實例進行綁定,這就是實例方法,類別方法,靜態方法的區別。

以上是python物件導向方法的區別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn