1. 程式人生 > >【20180421】python--repo:subcmds學習

【20180421】python--repo:subcmds學習

1.概述

在上一篇main.py學習中我們提到main.py涉及三種重要的資料結構,本篇針對其中的一種:all_commands物件列表展開分析。all_commands列表來自於repo工程中的subcmds這個模組包,通過python包匯入機制啟動__init__.py來遍歷subcmds包中所有cmd.py,並將其中定義的cmd類生成物件儲存到列表中,供main.py中呼叫。

2.資料結構

all_commands是一個列表,其中每一個元素都是一個物件,物件對應於以某個repo子命令首字母大寫命名的類,這些類均繼承於Commands類並各自重寫了Execute、_Options等方法用於差異化地執行各種repo子命令的功能。

3.主體思路

前提:python模組包在import時會自動執行__init__.py。

檔案結構:subcmds模組包中每一個py檔案都對應一個repo子命令並以子命令名稱命名,在每個py檔案中會定義repo子命令的對應類(從command類繼承)。

我們來看__init__.py的思路:

通過__file__獲取當前路徑開始遍歷所有檔案 -->

對以.py結尾的非__init__.py的檔案獲取其名稱name和首字母大寫後的name即clsn -->

code:  if py.endswith('.py'):
    name = py[:-3]
    clsn = name.capitalize()

使用內建函式__import__動態匯入subcmds路徑下名稱為name的submodule -->

code:  mod = __import__(__name__, globals(), locals(), ['%s' % name])

使用內建函式getattr獲取mod的名為name的module的名為clsn的類並建立物件cmd -->

code:  mod = getattr(mod, name)       cmd = getattr(mod, clsn)()

更新cmd的NAME屬性並將cmd放入列表中

code:  cmd.NAME = name     all[name] = cmd


4.演算法思路

repo對於subcmds模組包的使用方式值得借鑑,將不同場景的處理模式封裝成類,並在匯入模組包時例項化這些類的物件最後以列表的形式對外提供使用。

附內建函式__import__:

Python 提供內建函式 __import__ 動態載入 module,__import__ 的用法如下:

1 2 __import__ ( name [ , globals [ , locals [ , fromlist [ , level ] ] ] ] )  
  • name (required): 被載入 module 的名稱
  • globals (optional): 包含全域性變數的字典,該選項很少使用,採用預設值 global()
  • locals (optional): 包含區域性變數的字典,內部標準實現未用到該變數,採用預設值 local()
  • fromlist (Optional): 被匯入的 submodule 名稱
  • level (Optional): 匯入路徑選項,預設為 -1,表示同時支援 absolute import 和 relative import