第十屆鐵人賽 flask-restful DAY11-搞懂Python中如何使用以及建立自己的函式庫

import與module

在介紹完方法、類別與裝飾器後要更進一步讓程序可以重複利用的方式就是把之前所教授撰寫出來的方法、類別以及裝飾器打包起來變成函式庫。不過跟之前一樣,不會寫沒關係至少要會用,所以在教授大家將程序打包成函式庫前先告訴大家怎麼使用別人的函式庫。

import

這時又可以回顧到第一天的範例了,相信各位讀者有注意到下列式子在第一天的範例之中:

from flask import Flask
app = Flask(__name__)

使用函式庫相較之下簡單,不外乎就是from哪個函式庫,import哪個類別然後開始用,不過當然在用之前需要看看函式庫的api文件,瞭解一下該如何使用。

module

會使用函式庫後就可以試著做自己的函式庫了,其實這筆使用他人的函式庫簡單,基本上就依據程序內容分檔案、分資料夾,注意這邊的檔案副檔名需要是.pyfrom後面接的是.py檔案的路徑,而import後接的則是需要使用的類別。講那麼多,還是來看看下列例子:

-root
    |-lib
    |-app.py
        |-model
        |-__init__.py
            |-__init__.py
            |-classA.py

在上述資料結構下,若是要在app.py使用classA.py內的ClassA這類別只需參考下列例子:

from lib.model.classA import ClassA

接下來就像一般使用類別的方式使用即可。

__init__.py

相信眼尖的讀者會發現每個資料夾內都有這檔案,而且一定都想過可以刪掉他嗎?這裡筆者會建議你試試看,不過當然程序壞掉只能自己想辦法了,至於這檔案是什麼功用呢?其實他就是讓Python的編譯器知道資料夾內有函式庫的內容,若是沒有這檔案編譯器就不會尋訪這資料夾,而讀者就無法使用ClassA了。

__name__

說完了函式庫的使用以及撰寫,這裡來說明一些注意事項,相信大家對於第一天看到的一個語法__name__非常好奇,然而好幾天過去了也沒有說明該內容,究竟這個__name__是甚麼東西呢?而下列式子又代表甚麼意思呢?

if __name__ == '__main__':

由於python的每個.py都可以直接執行或者當作函式庫提供其他程序使用,再來每個.py亦可以撰寫執行的語法,例如下列例子一個test.py

class ClassTest:
    name = ''

    def __init__(self, name):
        self.name = name

    def printName(self):
        print(self.name)


cls = ClassTest('ClassName')
cls.printName()

相信當這個test.pyClassTest被當作函式庫在外部使用者使用時不會想要輸出以下內容:

cls = ClassTest('ClassName')
cls.printName()

不過在test.py被引用時就會執行以上內容,這時要如何處理這問題呢?請將上述的寫法改寫成以下的寫法:

if __name__ == '__main__':
    cls = ClassTest('ClassName')
    cls.printName()

簡單解釋這個解法就是當test.py直接被執行時__name__這個系統變數會有__main__的內容,但是若是由其他程序來import__name__則會是test.py的路徑,也就是之前介紹from的內容lib.model.classA

functools.wraps

在介紹這工具之前先請各位讀者看看下列式子,這是一個定義在函式庫的類別,類別中包含一個物件方法的裝飾器:

class ClassTest:
    name = ''

    def __init__(self, name):
        self.name = name

    @classmethod
    def printArgs(cls, arg):
        def decorator(func):
            def warpper(*args, **kwargs):
                print(func.__name__)
                print(func.__doc__)
                print(arg)
                return func(*args, **kwargs)

            return warpper

        return decorator

其中做了兩件事情print(func.__name__)print(func.__doc__),這兩件事情分別是印出函式的名稱,以及列出函式的文件說明。
然後再搭配以下例子來使用該函式庫內的類別:

from temp.test import ClassTest

@ClassTest.printArgs('Hello')
def printArgs(args):
    """ DOC """
    print(args)


printArgs('World')
print(printArgs.__name__)
print(printArgs.__doc__)

當執行上述式子會得到以下內容:

printArgs
 DOC
Hello
World
warpper
None

為什麼會這樣子呢?簡單講就是裝飾器把系統變數的內容給吃掉了,例如最後面的warpper應該要是printArgs,而最後的None應該是DOC才對,如果要解決這問題就需要一開始介紹的functools.wraps套件,但是這套件該如何使用呢,請把上述開始的例子改寫為底下的式子:

from functools import wraps


class ClassTest:
    name = ''

    def __init__(self, name):
        self.name = name

    @classmethod
    def printArgs(cls, arg):
        def decorator(func):
            @wraps(func)
            def warpper(*args, **kwargs):
                print(func.__name__)
                print(func.__doc__)
                print(arg)
                return func(*args, **kwargs)

            return warpper

        return decorator

相信各位讀者修改後執行應該會看到以下的內容:

printArgs
 DOC
Hello
World
printArgs
 DOC

小結

花了好幾天終於把Python的一些基礎以及坑說明給各位讀者知道了,終於要準備進入flask的一些內容了,所以想要知道flask-restful的還請在稍待片刻了,由於主題是flask-restful,所以不會帶太多flask的內容,若是僅對flask有興趣的可以參考其他人的文章,或是待筆者之後整理了。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *