Python 如何使用静态方法作为策略设计模式的默认参数?
我想创建一个类,该类使用与以下类似的策略设计模式:Python 如何使用静态方法作为策略设计模式的默认参数?,python,python-3.x,static-methods,strategy-pattern,default-parameters,Python,Python 3.x,Static Methods,Strategy Pattern,Default Parameters,我想创建一个类,该类使用与以下类似的策略设计模式: class C: @staticmethod def default_concrete_strategy(): print("default") @staticmethod def other_concrete_strategy(): print("other") def __init__(self, strategy=C.default_concrete_strat
class C:
@staticmethod
def default_concrete_strategy():
print("default")
@staticmethod
def other_concrete_strategy():
print("other")
def __init__(self, strategy=C.default_concrete_strategy):
self.strategy = strategy
def execute(self):
self.strategy()
这会产生以下错误:
name错误:未定义名称“C”
将strategy=C.default\u-concrete\u-strategy
替换为strategy=default\u-concrete\u-strategy
将起作用,但默认情况下,strategy实例变量将是静态方法对象,而不是可调用的方法
TypeError:“staticmethod”对象不可调用
如果我删除@staticmethod
装饰器,它会起作用,但是还有其他方法吗?我希望默认参数是自我记录的,以便其他人能够立即看到如何包含策略的示例
还有,有没有更好的方法来公开策略而不是静态方法?我认为在这里实现完整类没有意义。不,您不能,因为
类定义尚未完成运行,因此当前命名空间中还不存在类名
您可以直接使用函数对象:
class C:
@staticmethod
def default_concrete_strategy():
print("default")
@staticmethod
def other_concrete_strategy():
print("other")
def __init__(self, strategy=default_concrete_strategy.__func__):
self.strategy = strategy
定义方法时,C
还不存在,因此您可以通过本地名称引用default\u-concrete\u-strategy
.func
打开staticmethod
描述符以访问底层原始函数(staticmethod
描述符本身不可调用)
另一种方法是使用哨兵违约<代码>无在这里可以正常工作,因为策略
的所有正常值都是静态函数:
class C:
@staticmethod
def default_concrete_strategy():
print("default")
@staticmethod
def other_concrete_strategy():
print("other")
def __init__(self, strategy=None):
if strategy is None:
strategy = self.default_concrete_strategy
self.strategy = strategy
由于这从
self
检索default\u-concrete\u-strategy
,描述符协议被调用,并且(未绑定)函数在类定义完成后由staticmethod
描述符本身返回。策略模式在python中基本上是无用的。因为函数是第一类对象,所以只需传递函数即可。@Bakuriu正如您所见,策略是第一类对象函数。我认为这仍然被称为策略模式不?是的,但是策略模式主要是在不允许传递函数的语言中发明的。我的意思是,在你的类的99%的用例中,你可以简单地直接传递函数,并以较低的复杂性获得相同的结果。@Bakuriu你能举一个例子说明如何做到这一点吗?这也与问题有关,或者他可以先定义default\u-concrete\u-strategy
,而不用修饰它,然后在定义了\uuuuu init\uuuuu
之后对其进行装饰(就像2.4之前使用的装饰器一样),尽管这会很麻烦。@Bakuriu:没错;打开包装要容易得多。如果这是唯一的方法,那就太可惜了。如果能在代码中直接看到如何传递参数的示例,那就太好了@Bakuriu在构造函数中修饰方法会有帮助吗?@mtanti否。您必须在类中放置@staticmethod
。我的意思是def method():pass;def uuu init uuu(self,func=method):通过;方法=静态方法(方法)
。然而,我必须说,我更喜欢使用None
作为默认值,并在\uuu init\uuu
@mtanti中检查它:这不是唯一的方法,但它是最可读的方法。另一种方法是“手工”使用装饰器;定义default\u-concrete\u策略
而不使用@staticmethod
行,然后在定义了\u-init\u\u方法后,使用default\u-concrete\u策略=staticmethod(default\u-concrete\u策略)
。