Python导入函数从模块两次使用不同的内部导入

时间:2018-02-13 09:57:50

标签: python python-import

我有一个需要lib的模块numpy。所以,例如,让我们说我有一个看起来像

的假设函数
import numpy
def doSomething(x):
    return numpy.sqrt(x)

现在要在单独的模块中使用该功能,我将名称导入为

from lib import doSomething
...

这是一个棘手的部分......现在我想公开另一个doSomething版本,其中numpy已从另一个库(特别是autograd)导入。所以,例如,我希望能够有一个功能

from autograd import numpy
def doSomething(x):
    return numpy.sqrt(x)

这些函数之间的唯一区别在于导入numpy的位置。特别是,我想在同一代码中使用两个版本的doSomething,也就是说,我想要一些导入doSomething两次的方法...一次使用默认的numpy,和来自autograd的numpy一次。像这样:

useAutograd = False
from lib(useAutograd) import doSomething
useAutograd = True
from lib(useAutograd) import doSomething as doSomethingAutograd 

我知道这里有几个选项,但没有一个是令人满意的。

  1. 我会复制代码库,并使用默认的numpy,并使用numpy中的autograd。这很糟糕,因为它需要我维护两个代码库,这些代码库是彼此的副本,只有不同的导入。

  2. 我可以进行条件导入:

    try:
        from autograd import numpy
    except ImportError:
        import numpy
    

    这很糟糕,因为用户无法控制导入的版本...如果他们有自动编程,那么他们必须使用该版本。

  3. 我可以定义一个环境变量来控制导入

    import os
    if os.environ.get('AUTOGRADNUMPY'):
        try:
            from autograd import numpy
        except ImportError:
            import numpy
    else:
        import numpy
    

    这有一个缺点,即虽然用户可以控制导入,但他们只能选择一个版本(据我所知)。因此他们无法在同一代码中使用这两个版本。

  4. 这个用例有更好的替代方案吗?

    感兴趣的人的背景:

    Autograd有自己的一组函数,模仿numpy并允许人们使用自动差异(与张量流相同的方式)轻松计算导数,而无需昂贵的数值微分。

    但是,他们的numpy实现并不是最优化的版本(AFAIK)。因此,当用户需要该函数的jacobian时,允许用户使用带autograd导入的版本,并在他们不需要时使用他们默认的,高度优化的numpy包。 / p>

3 个答案:

答案 0 :(得分:3)

如果您希望避免重复代码库,请将您的界面改为一个类。例如:

class using_numpy:
    import numpy

    @classmethod
    def do_something(cls, x):
        return cls.numpy.sqrt(x)

class using_autograd(using_numpy):
    from autograd import numpy

现在using_numpy.do_something将使用numpyusing_autograd.do_something将使用autograd.numpy

或者,如果您对classmethod感到不舒服,可以创建类的接口实例,例如:

class interface:
    def __init__(self, mdl):
        self.mdl = mdl

    def do_something(self, x):
        return self.mdl.sqrt(x)

import numpy
import autograd

with_numpy = interface(numpy)
with_autograd = interface(autograd.numpy)

答案 1 :(得分:1)

您无需做任何事情来实现这一目标。

如果你这样做

from lib import doSomething
from lib_with_autograd import doSomething as doSomethingAutograd

每个函数都使用在其特定模块中导入的numpy。因此,doSomethingAutograd使用lib_with_autograd中导入的doSomethinglib使用AudioManager中导入的文件

答案 2 :(得分:1)

由于python中的所有内容都是一个对象,包括模块,因此您可以执行以下操作:

def doSomething(x, numpy=None):
    if numpy is None:
        import numpy
    return numpy.sqrt(x)

然后你可以在不设置numpy的情况下调用该函数,然后它将使用默认的numpy。如果你想使用另一个numpy,只需这样称呼它:

from autograd import numpy as autograd_numpy
doSomething(x, numpy=autograd_numpy)