关于python:如何使用静态方法作为策略设计模式的默认参数?

How can I use a static method as a default parameter for the strategy design pattern?

我想创建一个类,该类使用与此类似的策略设计模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()

这就产生了错误:

1
NameError: name 'C' is not defined

strategy=default_concrete_strategy替换strategy=C.default_concrete_strategy是可行的,但默认情况下,策略实例变量将是静态方法对象,而不是可调用方法。

1
TypeError: 'staticmethod' object is not callable

如果我移除@staticmethod装饰器,它会工作,但是还有其他方法吗?我希望默认参数是自记录的,这样其他人就可以立即看到如何包括策略的示例。

此外,是否有更好的方法来公开策略而不是静态方法?我不认为在这里实现完整的类是有意义的。


不可以,因为class定义尚未完成运行,所以当前命名空间中还不存在类名。

您可以直接使用函数对象:

1
2
3
4
5
6
7
8
9
10
11
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描述符本身不可调用)。

另一种方法是使用sentinel默认值;由于strategy的所有正常值都是静态函数,因此None在这里可以正常工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
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描述符本身返回,而类定义完成之后。