我的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!发布于 2015-11-23 18:53:50
在python中,这可以通过继承来最优雅地完成:
A.py:
import B
class SayHi(object):
b = B
def say_hi(self):
print "Message: " + self.b.greeting()my_B_impl.py:
class AlternativeHi(object):
def greeting(self):
return "Hallo!"main.py:
import A
from my_B_impl.py import AlternativeHi
class MyHi(SayHi):
b=AlternativeHi
a=MyHi()
MyHi.say_hi()输出:
Message: Hallo!您还可以使用工厂模式来避免显式声明类AlternativeHi和MyHi
A.py
from B import greeting
class SayHi(object):
def __init__(self,*args,**kwargs):
self.greeting = greeting
def say_hi(self):
print "Message: " + self.greeting()
def hi_factory(func):
class CustomHi(SayHi):
def __init__(self,*args,**kwargs):
result = super(CustomHi, self).__init__(*args, **kwargs)
self.greeting = func
return CustomHimy_B_impl.py:
def greeting(self):
return "Hallo!"main.py:
form A import hi_factory
from my_B_impl import greeting
a = hi_factory(greeting)
a.say_hi()发布于 2015-11-23 09:03:21
你问的问题不是直接可能的。Python的模块系统中没有内置的参数化功能。如果你仔细想想,就不清楚这样的建议应该如何工作:如果模块A和B都导入了模块M,但它们提供了不同的参数,那么在导入M时使用哪个参数?是否导入了两次?这对于模块级配置(就像在logging中)意味着什么?如果第三个模块C试图导入不带参数的M,情况会变得更糟。此外,您可以从外部覆盖任何import语句的“开放世界”思想违反了“您编写的代码就是运行的代码”的语言设计原则。
其他语言已经以不同的方式集成了参数化模块(比较Scala的对象模型、ML的模块和签名,以及C++的模板),但尚不清楚这样的特性是否适合Python. (也就是说,如果你有足够的决心和自虐精神,你可能会用importlib破解一些类似参数化模块的东西。)
然而,Python确实具有非常强大和灵活的动态分派功能。Python的标准、日常特性,如函数、类、参数和覆盖,为这种支持提供了基础。
有很多方法可以在你的函数示例中切开蛋糕,这个函数的行为可以由它的客户配置。
由值参数化的函数:
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 :在一条评论中,你提到你想要一个在模块级设置依赖的。这样做的主要问题是依赖关系是全局的-模块是单例的,因此任何导入模块的人都必须使用相同的依赖关系实现。
我的建议是提供一个具有“适当的”(每个实例)依赖注入的面向对象的API,并提供使用依赖的(可配置的)“默认”设置的顶级便利函数。然后您可以选择不使用全局配置的版本。这大致就是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()https://stackoverflow.com/questions/33855560
复制相似问题