我的python模块使用来自另一个模块的一些函数,但我有几个模块接口的实现。如何指出,使用哪一个?
简单示例:
A.py:
import B
def say_hi()
print "Message: " + B.greeting()
main.py:
import A(B=my_B_impl)
A.say_hi()
my_B_impl.py:
def greeting():
return "Hallo!"
输出:
Message: Hallo!
答案 0 :(得分:0)
你问的不是直接可能的。 Python的模块系统没有内置参数化功能。如果您考虑一下,不清楚这样的提案应该如何工作:如果模块A
和B
都导入模块M
,但它们提供不同的参数,当使用哪个参数时导入M
?是进口两次吗?这对于模块级配置意味着什么(如在logging
中)?如果第三个模块C
尝试导入M
而没有参数,情况会变得更糟。此外,您可以从外部覆盖任何 import
语句的“开放世界”理念违反了“您编写的代码就是运行的代码”的语言设计原则。 / p>
其他语言已经以各种方式合并了参数化模块(比较Scala的对象模型,ML的模块和签名,以及 - 拉伸它--C ++的模板),但是不清楚这样的特性是否适合Python。 (也就是说,如果你有足够的决心和自虐,你可能会使用importlib
破解类似于参数化模块的东西。)
有很多方法可以削减你的行为可由其客户配置的函数示例。
由值:
参数化的函数def say_hi(greeting):
print("Message: " + greeting)
def main():
say_hi("Hello")
由值:
参数化的类class Greeter:
def __init__(self, greeting):
self.greeting = greeting
def say_hi(self):
print("Message: " + self.greeting)
def main():
Greeter("Hello").say_hi()
具有虚拟方法的类:
class Greeter:
def say_hi(self):
print("Message: " + self.msg())
class MyGreeter(Greeter):
def msg(self):
return "Hello"
由函数参数化的函数:
def say_hi(greeting):
print("Message: " + greeting())
def make_greeting():
return "Hello"
def main():
say_hi(make_greeting)
还有更多选项(我正在避免使用Java-y对象调用其他对象的例子),但是你明白了。在每种情况下,行为的选择(参数的传递,方法的覆盖)与使用它的代码分离,并且可以放在不同的文件中。选择合适的人选取决于你的情况(虽然这里有一个提示:正确的一个总是最简单的一个)。
更新:在评论中,您提到您想要一个在模块级别设置依赖关系的API。这个问题的主要问题是依赖关系是 global - 模块是单例,因此导入模块的任何人都必须使用相同的依赖实现。
我的建议是提供一个面向对象的API,它具有“正确的”(每个实例)依赖注入,并提供顶级的便利功能,这些功能使用依赖性的(可配置的)“默认”设置。然后,您可以使用全局配置的版本选择 not 。这大约是how asyncio
does it。
# flexible object with dependency injection
class Greeter:
def __init__(self, msg):
self.msg = msg
def say_hi(self):
print("Message: " + self.msg)
# set up a default configuration of the object to be used by the high-level API
_default_greeter = Greeter("Hello")
def configure(msg):
global _default_greeter
_default_greeter = Greeter(msg)
# delegate to whatever default has been configured
def say_hi():
_default_greeter.say_hi()