溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么

發(fā)布時(shí)間:2021-10-26 17:23:13 來(lái)源:億速云 閱讀:169 作者:柒染 欄目:編程語(yǔ)言

這篇文章將為大家詳細(xì)講解有關(guān)Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

概述

秦人不暇自哀,而后人哀之;后人哀之而不鑒之,亦使后人而復(fù)哀后人也! –論面向文檔編程的重要性

如果想看見(jiàn)識(shí)一個(gè)人寫代碼的功力,注釋其實(shí)是區(qū)分老司機(jī)和小鮮肉的一個(gè)顯著的分界線(有沒(méi)有觀察到你們公司的領(lǐng)導(dǎo)基本都在開會(huì)或者寫文檔),通常情況下老司機(jī)的文檔量與代碼量是1:1的比例,而新人往往認(rèn)為寫完功能模塊就已經(jīng)可以完成任務(wù)了。生產(chǎn)環(huán)境中需要面對(duì)現(xiàn)實(shí)中大量復(fù)雜的業(yè)務(wù)邏輯和數(shù)據(jù)校驗(yàn)并與各方對(duì)接,文檔質(zhì)量和代碼質(zhì)量就被提升到了相同的高度。很多人沒(méi)有寫注釋的習(xí)慣,大多數(shù)不是因?yàn)閼卸?,一方面是沒(méi)有意識(shí)到寫文檔的好處,另一方面是不了解這方面的工具。畢竟從管理上依賴于人的主動(dòng)性是遠(yuǎn)不如依賴于工具有效的。本文介紹如何利用Python注釋提升文檔書寫的質(zhì)量以及效率的小技巧。

Python

在實(shí)際生產(chǎn)中,機(jī)器學(xué)習(xí)工作現(xiàn)在看起來(lái),白天像是個(gè)算法工程師的活,晚上就變成運(yùn)維+測(cè)試了。Python  一直以來(lái)也都受到測(cè)試工程師和運(yùn)維工程師的偏愛(ài),下面是幾個(gè)經(jīng)典的注釋活用case。

用注釋寫單元測(cè)試:doctest

Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么

單元測(cè)試是代碼開發(fā)環(huán)節(jié)必不可少的一環(huán),對(duì)于Bug定位和代碼質(zhì)量而言是非常重要的。現(xiàn)在最廣為人知的單元測(cè)試框架就是Unittest,它借鑒了Java中成熟的單元測(cè)試框架的JUnit。即使像Django還對(duì)這個(gè)框架有特殊的支持,然而在實(shí)現(xiàn)Unittest的時(shí)候會(huì)感覺(jué)確實(shí)比較啰嗦,setup,teardown…在維護(hù)單元測(cè)試的時(shí)候很多時(shí)候感覺(jué)力不從心。

一個(gè)巧妙的方式可以是通過(guò)doctest,用docstring注釋的方式來(lái)完成單元測(cè)試,由于每個(gè)方法def下面都先跟著一段測(cè)試用例,然后緊跟著就是代碼正文,這樣一來(lái)很方便我們測(cè)試現(xiàn)有代碼的質(zhì)量,另一方面又便于修改。

舉個(gè)例子:

def factorial(n):      """Return the factorial of n, an exact integer >= 0.         >>> [factorial(n) for n in range(6)]      [1, 1, 2, 6, 24, 120]      >>> factorial(30)      265252859812191058636308480000000      >>> factorial(-1)      Traceback (most recent call last):          ...      ValueError: n must be >= 0         Factorials of floats are OK, but the float must be an exact integer:      >>> factorial(30.1)      Traceback (most recent call last):          ...      ValueError: n must be exact integer      >>> factorial(30.0)      265252859812191058636308480000000         It must also not be ridiculously large:      >>> factorial(1e100)      Traceback (most recent call last):          ...      OverflowError: n too large      """         import math      if not n >= 0:          raise ValueError("n must be >= 0")      if math.floor(n) != n:          raise ValueError("n must be exact integer")      if n+1 == n:  # catch a value like 1e300          raise OverflowError("n too large")      result = 1      factor = 2      while factor <= n:          result *= factor          factor += 1      return result        if __name__ == "__main__":      import doctest      doctest.testmod()

上面是官網(wǎng)提供的一個(gè)求N的階乘函數(shù)示例,在docstring 中通過(guò)  >>>符號(hào)來(lái)開始一個(gè)單元測(cè)試,之后換行輸入預(yù)期結(jié)果即可。實(shí)際上就是復(fù)制粘貼一下調(diào)試過(guò)程和結(jié)果,真的再簡(jiǎn)單不過(guò)了,想實(shí)現(xiàn)TDD也因此變得非常輕松。

用注釋寫API文檔:apidoc

Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么

在我們完成機(jī)器學(xué)習(xí)模型后,想要提供一個(gè)對(duì)外服務(wù)的接口以貢獻(xiàn)我們的算力時(shí)就需要完備的API文檔,也是通過(guò)API的調(diào)用才能為我們的模型提供源源不斷的校驗(yàn)數(shù)據(jù),對(duì)于提升模型效果有非常實(shí)際的意義。對(duì)大多數(shù)人而言調(diào)用API來(lái)完成開發(fā)都是一件比較開心的事情,因?yàn)槲覀兛梢陨僮龊芏喙ぷ骶涂梢詫?shí)現(xiàn)強(qiáng)大功能。然而,當(dāng)我們需要對(duì)外提供API時(shí)就要面臨不一樣的考驗(yàn)了,接口鑒權(quán)、接口設(shè)計(jì)、版本控制、并發(fā)問(wèn)題、日志埋點(diǎn)&hellip;這些都是需要面對(duì)的新問(wèn)題,而利用  apidoc 可以很好地解決這些API文檔中常見(jiàn)的諸多問(wèn)題,相當(dāng)于通過(guò)模板提升了我們的接口設(shè)計(jì)的能力。

apidoc為Python提供了一種類似于 docstring 的方式來(lái)寫API文檔,從語(yǔ)法上看比較類似于 R中的roxygen,都需要用戶以 @xxx  符號(hào)作為一個(gè)開頭,隨后書寫相關(guān)的定義和功能。

舉個(gè)例子:

下面是一個(gè)API接口的定義方法,最核心的部分就是

  1. 路由

  2. GET/POST方法

  3. 名稱/分組

  4. 參數(shù)與調(diào)用例子

(這年頭沒(méi)有用例的代碼都是耍流氓)

"""  @api {get} /user/:id Request User information  @apiName GetUser  @apiGroup User     @apiParam {Number} id Users unique ID.    @apiSuccess {String} firstname Firstname of the User.  @apiSuccess {String} lastname  Lastname of the User.  """

我們可以直接擼一個(gè)官方示例來(lái)學(xué)習(xí)如何使用apidoc。

首先,下載示例源碼

git clone https://github.com/apidoc/apidoc  cd apidoc

然后,安裝 apidoc 組件

sudo npm install apidoc -g

接著,利用官方代碼來(lái)制作一個(gè)例子,并且訪問(wèn)即可。

apidoc -i example/ -o output/ -t template/  open output/index.html

幾個(gè)參數(shù)的含義如下:

-i:input,表示輸入的文件夾

-o:output,表示輸出文件夾

-t:template,表示模板文件,通過(guò)替換模板我們可以修改文檔皮膚

在 example 文件夾下,我們需要在apidoc.json  中填寫配置文件,定義文檔的header和footer部分內(nèi)容,其余的文件會(huì)被自動(dòng)識(shí)別出其中的docstring作為API文檔的一部分。

由于apidoc的官方文檔非常簡(jiǎn)單清晰,所以這里不過(guò)多強(qiáng)調(diào)語(yǔ)法。

Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么

apidoc 還為我們提供了接口調(diào)試的功能,在實(shí)際使用的時(shí)候要注意:

我們需要一個(gè)web server 才可以使用這個(gè)接口調(diào)試的功能

要注意跨域的問(wèn)題。

Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么

通過(guò)版本對(duì)比,我們還可以快速排查API接口的變化情況。需要注意的是這個(gè)功能要求我們要將歷史的文檔記錄也要保存在該目錄下的文件中,通常我們可以把歷史的注釋輸出到一個(gè)特定文件中保存。

總的來(lái)說(shuō),雖然,API文檔的書寫并不是一件難度非常高的事情,卻能體現(xiàn)系統(tǒng)模塊設(shè)計(jì)和用戶體驗(yàn)設(shè)計(jì)的功力,我們應(yīng)該對(duì)那些無(wú)代碼示例,無(wú)版本控制的API文檔say  no!

用注釋寫命令行接口:docopt

利用docopt,我們可以在注釋中直接聲明文件的命令行傳入?yún)?shù),而不需要通過(guò)  argvs變量來(lái)捕獲輸入值再做判斷,這在調(diào)用運(yùn)維腳本或者若干任務(wù)調(diào)度腳本的時(shí)候尤其管用,極大地提升了CLI的效率。

舉個(gè)例子:(此處代碼僅供參考)

"""Usage:    fiannceR.py tcp <host> <port> [--timeout=<seconds>]    fiannceR.py serial <port> [--baud=9600] [--timeout=<seconds>]    fiannceR.py -h | --help | --version     """  from docopt import docopt     if __name__ == '__main__':      arguments = docopt(__doc__, version='0.1.1rc')      print(arguments)
fiannceR.py tcp 0.0.0.0 3838

這里的 arguments 將傳出一個(gè)字典對(duì)象,以Key-Value的形式將命令行中的輸入值捕獲。

{'--baud': None,  '--help': False,  '--timeout': None,  '--version': False,  '-h': False,  '<host>': '0.0.0.0',  '<port>': '3838',  'serial': False,  'tcp': True}

總結(jié)

如果真的要從數(shù)據(jù)擼到模型、接口,那么一排注釋的畫面真是美得不敢想象。

"""unitest  >>> FinanceR('20161001')  21.01  """  def FinanceR(date):      price = get_price(date)      return(price)     class(BaseHandler):      def get(self):             """apidoc             @api {get} /price/:date 獲取當(dāng)前價(jià)格             @apiName GetPrice             @apiGroup Quota                @apiParam {Number} date 交易日期                @apiSuccess {String} price          """          date = self.get_argument('date',None)          try:              price = FinanceR(date)              self.write({'data':{'price':price},'response':{'message':'success','code':200}})          except Exception as e:              self.write({'data':None,'response':{'message':str(e),'code':404}})                """Usage:    fiannceR.py tcp <host> <port> [--timeout=<seconds>]    fiannceR.py serial <port> [--baud=9600] [--timeout=<seconds>]    fiannceR.py -h | --help | --version     """  from docopt import docopt     if __name__ == '__main__':      arguments = docopt(__doc__, version='0.1.1rc')      print(arguments)

關(guān)于Python開發(fā)者面向文檔編程的正確姿勢(shì)是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI