【发布时间】:2019-12-24 00:43:53
【问题描述】:
我是 Python 条件导入的新手,我正在考虑两种方法来设计我的模块。我会很感激关于我为什么要选择一个与另一个(或者是否存在更好的替代方案)的意见。
问题
我有一个程序需要在不同条件下调用结构相同但不同的模块。这些模块都具有相同的功能、输入、输出等,唯一的区别在于它们在各自的功能范围内做什么。例如,
# module_A.py
def get_the_thing(input):
# do the thing specific to module A
return thing
# module_B.py
def get_the_thing(input):
# do the thing specific to module B
return thing
选项 1
根据输入值,我会根据this answer 有条件地导入适当的模块。
if val == 'A':
import module_A
if val == 'B':
import module_B
选项 2
我使用输入变量将模块名称生成为字符串,然后使用this method 从基于该字符串的正确模块调用函数。我相信这需要我先导入所有模块。
import module_A
import module_B
in_var = get_input() # Say my input variable is 'A', meaning use Module A
module_nm = 'module_' + in_var
function_nm = 'get_the_thing'
getattr(globals()[module_nm], function_nm)(my_args)
这个想法是通过在运行时生成模块和函数名称来调用 module_A.get_the_thing()。这是一个仅用于一个函数调用的无聊示例,但在我的实际情况下,我将使用函数列表,只是想让事情变得简单。
任何关于哪一种设计更好的想法,或者是否存在优于这两种设计的任何想法?希望有任何理由为什么。当然,A 更简洁,可能更直观,但不确定这一定等同于良好的设计或性能差异。
【问题讨论】:
-
选项 1 似乎要好得多。 Python 在某些情况下会在加载特定于平台的内容时使用它。我不明白为什么 2 会更受欢迎。就个人而言,我每次看到
globals()[]时都会作呕。我认为我从未见过它用于解决任何问题的最佳选择(并不是说它们不存在,但它们似乎很少见) -
要使 1 工作,您可能希望改为使用
if val == 'A': import module_A as some_name; elif val == 'B': import module_B as some_name。如果导入的名称不同,它将无法正常工作,因为您需要稍后找出导入的名称。 -
@Carcigenicate 如果它是
from module_A import *和from module_B import *可以吗?然后你可以在不知道模块名称的情况下直接调用get_the_thing()。 -
@Barmar 这可行,但
import *不是一个好习惯。 Iirc,PEP8 明确不鼓励它,因为它污染了命名空间。 -
另一种方法是定义多个类,然后
if val == 'A': thing = classA() elif val == 'B': thing = classB()
标签: python design-patterns module