我正在模拟一个分布式系统,其中所有节点都遵循某些协议。这包括评估协议中的一些小变化。变化意味着单个方法的替代实现。 所有节点始终遵循相同的变体,这由实验配置决定(在任何给定时间只有一个配置处于活动状态)。在不牺牲性能的情况下,最明智的方法是什么?
由于实验可能相当广泛,我显然不希望任何条件。在我刚使用继承之前,比如:
class Node(object):
def dumb_method(self, argument):
# ...
def slow_method(self, argument):
# ...
# A lot more methods
class SmarterNode(Node):
def dumb_method(self, argument):
# A somewhat smarter variant ...
class FasterNode(SmarterNode):
def slow_method(self, argument):
# A faster variant ...
但现在我需要测试所有可能的变种并且不希望指数数量的类混乱源。我还希望其他人偷看代码,以最小的努力来理解它。你有什么建议吗?
编辑:有一点我没有强调:对于所有预想的用例,似乎在配置时修补类是好的。我的意思是:它可以通过简单的Node.dumb_method = smart_method
来工作。但不知怎的,它没有感觉正确。这种解决方案会给随机的智能读卡器造成严重的麻烦吗?
答案 0 :(得分:2)
您可以使用__slots__
机制和工厂类。您需要为每个实验实例化一个NodeFactory
,但它会从那里为您创建Node
个实例。例如:
class Node(object):
__slots__ = ["slow","dumb"]
class NodeFactory(object):
def __init__(self, slow_method, dumb_method):
self.slow = slow_method
self.dumb = dumb_method
def makenode(self):
n = Node()
n.dumb = self.dumb
n.slow = self.slow
return n
示例运行:
>>> def foo():
... print "foo"
...
>>> def bar():
... print "bar"
...
>>> nf = NodeFactory(foo, bar)
>>> n = nf.makenode()
>>> n.dumb()
bar
>>> n.slow()
foo
答案 1 :(得分:2)
您可以使用type
功能创建新的子类型。您只需将子类命名空间作为dict。
# these are supposed to overwrite methods
def foo(self):
return "foo"
def bar(self):
return "bar"
def variants(base, methods):
"""
given a base class and list of dicts like [{ foo = <function foo> }]
returns types T(base) where foo was overwritten
"""
for d in methods:
yield type('NodeVariant', (base,), d)
from itertools import combinations
def subdicts(**fulldict):
""" returns all dicts that are subsets of `fulldict` """
items = fulldict.items()
for i in range(len(items)+1):
for subset in combinations(items, i):
yield dict(subset)
# a list of method variants
combos = subdicts(slow_method=foo, dumb_method=bar)
# base class
class Node(object):
def dumb_method(self):
return "dumb"
def slow_method(self):
return "slow"
# use the base and our variants to make a number of types
types = variants(Node, combos)
# instantiate each type and call boths methods on it for demonstration
print [(var.dumb_method(), var.slow_method()) for var
in (cls() for cls in types)]
# [('dumb', 'slow'), ('dumb', 'foo'), ('bar', 'slow'), ('bar', 'foo')]
答案 2 :(得分:0)
我不确定你是否正在尝试做类似于此的事情(允许换出运行时“继承”):
class Node(object):
__methnames = ('method','method1')
def __init__(self, type):
for i in self.__methnames:
setattr(self, i, getattr(self, i+"_"+type))
def dumb_method(self, argument):
# ...
def slow_method(self, argument):
# ...
n = Node('dumb')
n.method() # calls dumb_method
n = Node('slow')
n.method() # calls slow_method
或者如果您正在寻找类似的东西(允许运行(并因此测试)该类的所有方法):
class Node(object):
#do something
class NodeTest(Node):
def run_tests(self, ending = ''):
for i in dir(self):
if(i.endswith(ending)):
meth = getattr(self, i)
if(callable(meth)):
meth() #needs some default args.
# or yield meth if you can
答案 3 :(得分:0)
您可以使用metaclass。
如果允许您根据每个变体动态创建一个类。
答案 4 :(得分:0)
在实例化类或之后,是否应该调用要调用的方法?假设它是在实例化类时,以下内容如何:
class Node():
def Fast(self):
print "Fast"
def Slow(self):
print "Slow"
class NodeFactory():
def __init__(self, method):
self.method = method
def SetMethod(self, method):
self.method = method
def New(self):
n = Node()
n.Run = getattr(n, self.method)
return n
nf = NodeFactory("Fast")
nf.New().Run()
# Prints "Fast"
nf.SetMethod("Slow")
nf.New().Run()
# Prints "Slow"