上下文
我试图在我的代码中添加一些“插件”(我不确定这是否是正确的定义)。我所说的“插件”是指一个模块,它定义了一个模型(这是一个科学代码),这样它的存在就足以在代码中的任何其他地方使用它。
当然,这些插件必须遵循一个模板,该模板使用我的代码中定义的一些模块/函数/类。以下是我的代码相关部分的一个小片段:# [In the code]
class AllModels():
def __init__(self):
"""
Init.
"""
self.count = 0
def register(self, name, model):
"""
Adds a model to the code
"""
setattr(self, name, model)
self.count += 1
return
class Model():
def __init__(self, **kwargs):
"""
Some constants that defines a model
"""
self.a = kwargs.get("a", None)
self.b = kwargs.get("b", None)
# and so on...
def function1(self, *args, **kwargs):
"""
A function that all models will have, but which needs:
- to have a default behavior (when the instance is created)
- to be redefinable by the "plugin" (ie. the model)
"""
# default code for the default behavior
return
instance = AllModels()
以下是“插件”的相关部分:# [in the plugin file]
from code import Model, instance
newmodel = Model(a="a name", b="some other stuff")
def function1(*args, **kwargs):
"""
Work to do by this model
"""
# some specific model-dependent work
return
instance.register(newmodel)
附加信息和要求function1对于任何模型插件都具有完全相同的签名,但是
通常为每个人做不同的工作。
我想要function1的默认行为,如果不是
由插件定义,我仍然可以做一些事情(尝试
不同的可能性,和/或提出警告/错误)。
在插件中,function1可以使用一些仅在此插件中定义的其他函数。我之所以这样说是因为代码是与多处理模块一起运行的,我需要instance的AllModels实例能够在子进程中调用function1。instance在父进程和模型插件中定义,但将在不同的子进程中使用(尽管没有对其进行任何修改)。
当插件“重新定义”时,function1能够访问Model实例的属性(即self)将是非常棒的。
问题
我读过许多不同的python文档来源和一些SO问题。我只看到了解决这个问题的三分之二的可能办法:
1)不在Model类中声明function1方法,而是在插件创建新实例时将其设置为属性。# [in the plugin file]
def function1(*args, **kwargs):
# ....
return
newmodel.function1 = function1
然后在需要的时候给它打电话。在这种情况下,对象Model中的属性function1可能会初始化为None。其中一个警告是没有function1的“默认行为”(必须在代码中处理,例如测试if instance.function1 is None: ...),更大的警告是我不能通过这种方式访问self。。。
2)以某种方式使用python装饰器。我从未使用过这个,我读过的文档也不是那么简单(我的意思是,由于它的使用有很多可能性,所以不能直接使用)。但这似乎是一个很好的解决办法。不过,我担心它的性能影响(我听说它可能会减慢修饰函数/方法的执行速度)。如果这个解决方案是最好的选择,那么我想知道如何使用它(可能是一个简短的片段),以及是否可以使用类Model的属性:# [in the plugin file]
@mydecorator
def function1(self, *args, **kwargs):
"""
I'm not sure I can use *self*, but it would be great since some attributes of self are used for some other function similar to *function1*...
"""
# some stuff using *self*, eg.:
x = self.var **2 + 3.4
# where self.var has been defined before, eg.: newmodel.var = 100.
3)使用模块types及其MethodType。。。我不确定这和我的案子有关。。。但我可能错了。
正如您可能在这个长问题之后看到的,我不太熟悉这样的python特性,而且我现在对decorators的理解非常差。在继续阅读一些文档的同时,我认为在这里提出这个问题可能是值得的,因为我不确定处理我的问题的方向。
解决方案
森德勒的回答之美在于它确实简单明了。。。错过了真是太可惜了。很抱歉这个问题污染了我们。