2017/10/19

動態呼叫 module - python

在寫程式上我們會常遇到使用不同的參數動態的呼叫他的 class,在 PHP 會使用 call_user_funcall_user_func_array 來達到這個目的,而 node.js 載入 module 本來就是可以使用變數所以相對簡單,舉例來說

tester.js
module.exports = {
    test() {
        console.log('test');
    }
};
main.js
moduleName = 'tester';
const tester = require(`./${moduleName}`);

tester.test();
$ node main.js
test

不過 python 載入模組的方式無法使用字串,但可以透過 __import__ 以及 getattr 這兩個方式組合達到我們要的目的,檔案的結構如下:

transportation/
	__init__.py
	base.py
	bike.py
	car.py
main.py
base.py
class Base(object):
    def go(self):
        print('go with {excute_name}'.format(excute_name=self.excute_name))

這隻 module 簡單來講就是 car 以及 bike 共同繼承的工具,目的在測試這樣的載入方式使用繼承會不會有問題

car.py
from base import Base

class Car(Base):
    excute_name = 'car'

基本上只是初始化一個 module,放一個 property

bike.py
from base import Base

class Bike(Base):
    excute_name = 'bike'

同上

main.py
# -*- coding: utf-8 -*-

transportations = [
    'car',
    'nope',
    'bike'
]

for transportation in transportations:
    class_name = transportation.capitalize() # 字首改大寫即為 class name
    module_name = 'transportation.{name}'.format(name=transportation)

    try:
        module = __import__(module_name, globals(), locals(), [class_name])
        collector = getattr(module, class_name)()
        collector.go()
    except Exception as e:
        print(str(e))

我們把要呼叫的 module 寫成一個 array 跑迴圈,中間我故意放了一個不存在的 module,程式碼裡面有使用 try exception,所以不用怕出錯會中斷,執行程式結果如下

$ python main.py
go with car
No module named nope
go with bike

沒有留言: