Hug*_*lle 1 python inheritance strategy-pattern
语境
我正在尝试在 Python 2.7 中实现策略模式的一些变体。我希望能够实例化“my_strategy”基类,但在运行时在“score”方法的不同实现之间切换。我将在“my_strategy”中有许多常用方法,但有一堆“score”实现。主要说明了我想如何使用它。当然,这里的评分实现是虚拟的。
我尝试过的(即到目前为止我的代码)
策略.py:
from algo_one import *
#from algo_two import *
class my_strategy ( object ):
def __init__(self, candidate = ""):
self.candidate = candidate
self.method = 'default'
self.no = 10
self._algo = algo_one
def set_strategy(self, strategy='default'):
self.strategy = strategy
if self.strategy == 'algo_one':
self._algo = algo_one
elif self.strategy == 'algo_two':
# self._algo = algo_two
pass
else:
self._algo = None
def score(self, *args):
if len(args) > 0:
self.candidate = args[0]
self._algo.score(self.candidate)
if __name__ == "__main__":
s = my_strategy()
s.strategy = 'algo_one'
s.candidate = "hello world"
print s.score()
print s.score("hi")
# s.set_method('algo_two')
# print s.score("hi")
Run Code Online (Sandbox Code Playgroud)
我想将选定的策略保存在某种指向子类方法的私有指针中。
algo_one.py:
from strategy import my_strategy
class algo_one ( my_strategy ):
def score(self, candidate):
return len(candidate)*self.no
Run Code Online (Sandbox Code Playgroud)
我可以有一个无类方法,但稍后我需要访问基类的公共变量。
算法_two.py:
from strategy import my_strategy
class algo_two ( my_strategy ):
def score(self, candidate):
return len(candidate)*3
Run Code Online (Sandbox Code Playgroud)
我也有一个空的init .py 。
错误
1. 在分数 self._algo.score(self.candidate)
类型错误:必须使用 algo_one 实例作为第一个参数调用未绑定方法 Score()(改为使用 str 实例)
2. 如果我取消注释第二个策略的导入:
from algo_two import *
Run Code Online (Sandbox Code Playgroud)
我收到以下错误。
导入错误:无法导入名称 my_strategy
我的猜测是我遇到了某种循环依赖。
3.
from algo_one import *
Run Code Online (Sandbox Code Playgroud)
这显然不太漂亮(无法检测未定义的名称),但如果我
from algo_one import algo_one
Run Code Online (Sandbox Code Playgroud)
我明白了
导入错误:无法导入名称 algo_one
问题
我认为这些错误是交织在一起的,而且我的方法作为一个整体可能存在缺陷。如果不仅仅是解决错误,我还会寻找改进设计的建议。或者任何评论,真的。我也愿意接受有关这个问题标题的建议。谢谢你!
你让它变得比需要的更加复杂。Python 函数是第一类对象,因此在 Python 中实现策略模式的最简单方法是将“策略”函数传递给“上下文”对象(使用该策略的对象)。最好的部分是任何可调用对象(即:任何实现该__call__方法的对象)都可以工作。
def default_score_strategy(scorer):
return len(scorer.candidate) * 3
def universal_answer_score_strategy(scorer):
return 42 # definitly the universal answer <g>
class ComplicatedStrategy(object):
def __init__(self, factor):
self.factor = factor
def __call__(self, scorer):
return len(scorer.candidate) * self.factor
class Scorer(object):
def __init__(self, candidate="", strategy=default_score_strategy):
self.candidate = candidate
self.strategy = strategy
def score(self):
return self.strategy(self)
s1 = Scorer("foo")
s2 = Scorer("bar", strategy=universal_answer_score_strategy)
s3 = Scorer("baaz", strategy=ComplicatedStrategy(365))
Run Code Online (Sandbox Code Playgroud)
请注意,您的策略不必与类位于同一模块中Scorer(当然,默认的除外),并且包含该类的模块Scorer不必导入策略模块 - 也不知道策略在哪里定义为:
# main.py
from mylib.scores import Scorer
from myapp.strategies import my_custom_strategy
s = Scorer("yadda", my_custom_strategy)
Run Code Online (Sandbox Code Playgroud)