8

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

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_strategystrategy=default_concrete_strategy将起作用,但默认情况下,策略实例变量将是静态方法对象而不是可调用方法。

TypeError: 'staticmethod' object is not callable

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

另外,有没有更好的方法来公开策略而不是静态方法?我认为在这里实施完整的课程没有意义。

4

1 回答 1

14

不,您不能,因为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

由于调用了default_concrete_strategyself描述符中检索的协议,并且描述符本身返回了(未绑定的)函数,因此staticmethod在类定义完成之后。

于 2014-02-10T08:27:13.740 回答