如何使用静态方法作为策略设计模式的默认参数?
Posted
技术标签:
【中文标题】如何使用静态方法作为策略设计模式的默认参数?【英文标题】:How can I use a static method as a default parameter for the strategy design pattern? 【发布时间】:2014-03-07 11:30:17 【问题描述】:我想创建一个使用类似这样的策略设计模式的类:
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()
这给出了错误:
NameError: name 'C' is not defined
将strategy=C.default_concrete_strategy
替换为strategy=default_concrete_strategy
将起作用,但默认情况下,策略实例变量将是静态方法对象而不是可调用方法。
TypeError: 'staticmethod' object is not callable
如果我删除 @staticmethod
装饰器,它会起作用,但还有其他方法吗?我希望自行记录默认参数,以便其他人立即看到如何包含策略的示例。
另外,有没有更好的方法来公开策略而不是静态方法?我认为在这里实现完整的类没有意义。
【问题讨论】:
策略模式在python中大多没用。由于您将函数作为第一类对象,因此您可以传递函数。 @Bakuriu 正如您所见,该策略是一流的对象函数。我认为这仍然被称为策略模式不是吗? 是的,但是策略模式主要是在不允许传递函数的语言中发明的。我的意思是,在你的类的 99% 的用例中,你可以简单地直接传递函数并以更低的复杂性获得相同的结果。 @Bakuriu 你能举例说明如何做到这一点吗? 也与问题Calling class staticmethod within the class body?有关 【参考方案1】:不,您不能,因为 class
定义尚未完成运行,因此当前命名空间中尚不存在类名。
你可以直接使用函数对象:
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_concrete_strategy
。 .__func__
解包 staticmethod
描述符以访问底层原始函数(staticmethod
描述符本身不可调用)。
另一种方法是使用哨兵默认值; None
在这里可以正常工作,因为 strategy
的所有正常值都是静态函数:
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_concrete_strategy
,因此调用描述符协议并由staticmethod
描述符本身返回(未绑定)函数,在类定义完成之后。
【讨论】:
或者他可以先定义default_concrete_strategy
不装饰它,然后在__init__
的定义之后装饰它(因为装饰器在2.4之前使用),虽然这样会很麻烦。
@Bakuriu:完全正确;拆开包装要容易得多。
如果这是唯一的方法,那就太可惜了。如果直接在代码中看到如何传递参数的示例,那就太好了。 @Bakuriu 在构造函数中装饰一个方法会有帮助吗?
@mtanti 不,你必须把@staticmethod
放在课堂上。我的意思是def method():pass; def __init__(self, func=method):pass; method = staticmethod(method)
。但是我必须说,我更喜欢简单地使用 None
作为默认值并在 __init__
中检查它。
@mtanti:这不是唯一的方法,但它是最易读的方法。另一种方法是“手动”应用装饰器;定义default_concrete_strategy
不带 @staticmethod
行,然后在定义__init__
方法后,使用default_concrete_strategy = staticmethod(default_concrete_strategy)
。以上是关于如何使用静态方法作为策略设计模式的默认参数?的主要内容,如果未能解决你的问题,请参考以下文章
Java基础 -- 静态方法和实例方法有何不同无参构造函数有什么作用import java和javax有什么区别成员变量与局部变量的区别有哪些(成员变量有默认赋值)