我正在模拟一个分布式系统,其中所有节点都遵循某种协议(protocol)。这包括评估协议(protocol)中的一些小变化。变体意味着单一方法的替代实现。 所有节点始终遵循相同的变化,这是由实验配置决定的(在任何给定时间只有一个配置处于事件状态)。在不牺牲性能的情况下,最清晰的方法是什么?
由于实验可能非常广泛,因此我显然不需要任何条件。在我刚刚使用继承之前,例如:
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
来工作。但不知何故,感觉不太对劲。这种解决方案会让随机的聪明读者感到头疼吗?
最佳答案
您可以使用type
函数创建新的子类型。您只需将子类 namespace 作为字典提供给它即可。
# 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')]
关于python - 在Python中配置类的最优雅的方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6680029/