Python 使用不同的内部导入从模块导入函数两次
Python import functions from module twice with different internal imports
我有一个模块 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
我知道这里有几个选项,但 none 令人满意。
我会复制一份代码库,一份使用默认的 numpy
,一份使用 autograd
中的 numpy
。这很糟糕,因为它需要我维护两个代码库,它们是彼此的副本,只有不同的导入。
我可以放入条件导入:
try:
from autograd import numpy
except ImportError:
import numpy
这很糟糕,因为用户无法控制导入的版本...如果他们有 autograd,那么他们必须使用该版本。
我可以定义一个环境变量来控制导入
import os
if os.environ.get('AUTOGRADNUMPY'):
try:
from autograd import numpy
except ImportError:
import numpy
else:
import numpy
缺点是虽然用户可以控制导入,但他们只能选择一个版本(据我所知)。所以他们不能在同一代码中使用这两个版本。
这个用例是否有更好的替代方案?
感兴趣者的背景:
Autograd
有自己的一组函数,模仿 numpy
并允许使用自动微分(与 tensorflow 相同)轻松计算导数,而不需要昂贵的数值微分。
但是,他们的 numpy 实现不是最优化的版本 (AFAIK)。因此,允许用户在需要函数的 jacobian 时使用带有 autograd
导入的版本,并在不需要时使用默认的、高度优化的 numpy 包是有利的。
您无需执行任何操作即可实现此目的。
如果你这样做
from lib import doSomething
from lib_with_autograd import doSomething as doSomethingAutograd
这些函数中的每一个都使用在其特定模块中导入的 numpy
。所以 doSomethingAutograd
使用 lib_with_autograd
中导入的那个,doSomething
使用 lib
中导入的那个
如果您希望避免重复您的代码库,请将您的界面改为 class。例如:
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
将使用 numpy
,而 using_autograd.do_something
将使用 autograd.numpy
。
或者,如果您对 classmethod
感到不舒服,您可以将接口实例化为 class,例如:
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)
由于 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)
我有一个模块 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
我知道这里有几个选项,但 none 令人满意。
我会复制一份代码库,一份使用默认的
numpy
,一份使用autograd
中的numpy
。这很糟糕,因为它需要我维护两个代码库,它们是彼此的副本,只有不同的导入。我可以放入条件导入:
try: from autograd import numpy except ImportError: import numpy
这很糟糕,因为用户无法控制导入的版本...如果他们有 autograd,那么他们必须使用该版本。
我可以定义一个环境变量来控制导入
import os if os.environ.get('AUTOGRADNUMPY'): try: from autograd import numpy except ImportError: import numpy else: import numpy
缺点是虽然用户可以控制导入,但他们只能选择一个版本(据我所知)。所以他们不能在同一代码中使用这两个版本。
这个用例是否有更好的替代方案?
感兴趣者的背景:
Autograd
有自己的一组函数,模仿 numpy
并允许使用自动微分(与 tensorflow 相同)轻松计算导数,而不需要昂贵的数值微分。
但是,他们的 numpy 实现不是最优化的版本 (AFAIK)。因此,允许用户在需要函数的 jacobian 时使用带有 autograd
导入的版本,并在不需要时使用默认的、高度优化的 numpy 包是有利的。
您无需执行任何操作即可实现此目的。
如果你这样做
from lib import doSomething
from lib_with_autograd import doSomething as doSomethingAutograd
这些函数中的每一个都使用在其特定模块中导入的 numpy
。所以 doSomethingAutograd
使用 lib_with_autograd
中导入的那个,doSomething
使用 lib
如果您希望避免重复您的代码库,请将您的界面改为 class。例如:
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
将使用 numpy
,而 using_autograd.do_something
将使用 autograd.numpy
。
或者,如果您对 classmethod
感到不舒服,您可以将接口实例化为 class,例如:
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)
由于 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)