python3 開發之一:classmethod和staticmethod

1.staticmethod

對於一般的計算機語言,都會提供靜態方法,這個方法可以認爲是類的方法。即可以直接 類.方法(),也可以通過類的實例,也就是對象.方法()進行調用。就靜態方法這方面來說,python語言和其他提供了靜態方法的語言來說並沒什麼區別。

比如在java中,main方法(主函數)就是一個靜態方法。

class Test
{
    public static void main(String[] args)
    {
        //code
    }
}

而在python中則採用裝飾器的形式(python中並沒有主函數的概念),即@staticmethod

class Test(object):
    @staicmethod
    def main():
        pass

以上兩者雖然在形式上有所不同,但是在使用上是一樣的。

擴展閱讀:裝飾器

2.classmethod

從字面上來看,classmethod的意思是類方法,看起來和staticmethod類似,但其實不然,不過它們還是有相似之處的。

相似之處

  1. classmethod和staticmethod修飾符對應的函數不需要實例化,即不需要self參數。
  2. 可以調用的屬性和方法。

除了上面提到的之外,它們兩個的用法則是南轅北轍。比如,classmethod的第一個參數cls來表示類(默認情況)。


接下來,以一個具體的場景來說明。

假設要使用python3自己開發一個ORM(Object Relate Mapping,對象關係映射)。

數據庫中有一個user表, 主鍵是uid,其他的還有name 名字、password 密碼。那麼在程序中使用時就需要查表來獲取對應的數據,並把一列數據封裝成一個對象。也就是說,程序需要一個從數據庫的數據到python對象的映射,這個映射就叫做ORM。

本篇不打算具體講解是如何映射的,想要具體瞭解的可以點這裏

假設你已經把基礎的工作都做好了,那麼此時的UML圖如下所示:

 即Model繼承自dict,並提供了一些通用的函數。比如find()方法,就是根據主鍵查表獲取滿足條件的數據。

對於python來說,這個方法是可以放在Model中的,那就是使用到classmethod裝飾器:

class Model(dict, metaclass=ModelMetaclass):
    #...
    @classmethod
    def find(cls, pk):
        """find object by primary key"""
        sql = '%s where `%s`=?' % (cls.__select__, cls.__primary_key__)
        rs = db.select_one(sql, pk)

        if rs is None:
            return None
        return cls(**rs)

上面的代碼比較簡單,功能就是根據主鍵來進行查表,如果找到對應的數據項(db.select_one返回的是dict或者None),則調用cls的構造方法來創建cls類的一個實例。

如果不使用classmethod而是使用staticmethod的話,就只能把上面的方法稍微修改後放到User當中。

class User(Model):
    #...
    @staticmethod
    def find(pk):
        """find object by primary key"""
        sql = '%s where `%s`=?' % (User.__select__, User.__primary_key__)
        rs = db.select_one(sql, pk)

        if rs is None:
            return None
        return User(**rs)

綜合比較上面的代碼就可以發現,兩者的代碼基本一致,只不過由通用的cls轉到了具體的User而已。

換句話說,在python3中,類本身也可以作爲一個變量來傳遞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章