Python导入基于输入参数

时间:2015-09-18 16:47:34

标签: python

我有一个看似简单的Python代码设计问题,我还没有找到任何优雅的解决方案。我有一组模块(下面的例子中有两个)定义了相同名称的函数,它们使用不同的算法计算相同的东西:

algorithm_a.py:

def compute_1(x):
   # do some computation
   return (x+1.)**2

def compute_2(x):
   # do some other computation

# etc

algorithm_b.py:

def compute_1(x):
   # do same computation in another way
   return x*x + 2.0*x + 1.0

def compute_2(x):
   # do some other computation in another way

# etc

这两个模块大约有10个功能,但未来这个数字可能会增长。

在第三个模块中,我定义的函数不知道如何执行计算的细节,即它们只关心获得正确的答案。用户的界面由类提供。总而言之,第三个模块看起来类似于:

simulation.py:

import XXX as algo #????

def do_computation_1(x):

   v1 = algo.compute_1(x)
   v2 = algo.compute_2(x)

   # Do some computations using v1, v2 
   return result

def do_computation_2(x):
   return algo.compute_2(x)

# etc etc

class Simulation(object):

  def __init__(self, method):
     # Do some magic here so that
     # if method == "A":
     #   algo = algorithm_a
     # if method == "B"
     #   algo = algorithm_b

  def run(self, x):
     do_computation_1(x)
     do_computation_2(x)

如何在do_computation()中加载和应用正确的模块,以取决于提供给类的方法参数?

请注意,do_computation函数需要保留在Simulation类之外。

结论:以下@BrenBarn的评论总结了可用的选项。谢谢大家的帮助!

2 个答案:

答案 0 :(得分:1)

更好的方法是实际保存(或传递)您想要使用的功能。例如。

import algorithm_a
import algorithm_b


class Simulation(object):

  def __init__(self, method):
     # Do some magic here so that
     if method == "A":
       self.compute_func = algorithm_a.compute
     if method == "B"
       self.compute_func = algorithm_b.compute

  def run(self, x):
     self.compute_func(x)

如果你真的必须有你的外部def do_computation(x)功能,你可以传递你想用作参数的算法

def do_computation(x, compute):
   return compute(x)

class Simulation(object):

  def __init__(self, method):
     # Do some magic here so that
     if method == "A":
       self.compute_func = algorithm_a.compute
     if method == "B"
       self.compute_func = algorithm_b.compute

  def run(self, x):
     do_computation(x, self.compute_func)

答案 1 :(得分:0)

通过构建代码的方式,您无法根据传递给类的参数进行导入。 Python文件从上到下执行。您的导入发生在类定义之前,因此在定义类时,导入已经发生。 (并且你不会传递method,直到你实例化这个类,这将会更晚。)

如果可以导入两个模块并且您只想使用指定的模块,那么您几乎可以按照字面意义完成您在评论中所写的内容:

import algorithm_a
import algorithm_b

class Simulation(object):

    def __init__(self, method):
        if method == "A":
            self.algo = algorithm_a
        if method == "B"
            self.algo = algorithm_b

    def do_computation(self, x):
        return self.algo.compute(x)

    def run(self, x):
        self.do_computation(x)

(我在这里使do_computation成为了类的一个方法。如果它的行为是由传递给类的参数决定的,那么将它作为一个单独的函数是没有意义的。)< / p>

如果模块的实际导入速度很慢,您可以有条件地导入一个模块或者如Reblochon的答案中所示的那样。但是,要执行此操作,必须将导入放在类中。如果您要通过类似Simulation("A")的内容指定算法,则无法确定在执行import simulation时要执行的导入,因为您还没有指定当时的算法;你必须等到实际打电话给Simulation("A")。 (如果导入速度很慢,这将导致此时减速,这可能是不可取的。)

编辑:如果你真的需要do_computation因为Numba而成为一个全局函数,你可以通过设置一个全局变量来解决它。将__init__更改为:

def __init__(self, method):
    global algo
    if method == "A":
        algo = algorithm_a
    if method == "B"
        algo = algorithm_b

制作一个像这样的全局do_computation函数:

def do_computation(x):
    return algo.compute(x)

这将更加令人困惑,因为每次创建新的Simulation时,它都会改变全局行为,即使对于以前创建的模拟也是如此。但如果你不能同时使用不同的算法创建多个模拟,那应该没问题。