让我们用start
方法创建一个类。它可以被多次调用,但实际的启动代码应该只执行一次。后续调用不应执行任何操作。(一个奇特的词是幂等)
听起来很简单:
class C:
def __init__(self):
self._started = False
def start(self):
if self._started:
return
# start code
print('start')
self._started = True
问题是,必须在所有衍生方法中重复试验:
class C2(C):
def start(self):
if self._started: # don't forget!
return
# additional code
super().start()
# additional code
我的解决方案#1:
我将start
分为两个函数:
class C:
def __init__(self):
self._started = False
def start(self):
# DO NOT OVERRIDE THIS ONE
if self._started:
return
self._start()
self._started = True
def _start(self):
# start code
print('start!')
class C2(C):
def _start(self):
# additional code
super()._start()
# additional code
第二次尝试在第一次调用后用noop func替换start
方法(确切地说,它在实例中创建了一个noop函数,该函数将类中的方法隐藏起来,但效果是相同的)。你知道吗
class C:
def start(self):
# start code
print('start!')
self.start = lambda: None
class C2(C):
def start(self):
# additional code
super().start()
# additional code
我对我的解决方案不满意,你知道更好的吗?你知道吗
更新:我不喜欢的是:
#1:要修改start
,您不能触摸start
,而是要修改其他函数
#2:是自修改代码
您可以创建一个函数来执行以下操作:
注意,在子类中,必须显式地添加
exec_once(self)
。你知道吗在派生类中重写的内容可能不是公共接口的元素,而是实现该接口的部分的某个内部函数的想法称为non-virtual interface pattern。当一个公共方法有几个这样的部分时,它通常被称为“模板方法”。术语来自C++(最初来自Simula),在这里可以执行这样的模式,因为只有{< CD1> }函数可以“EEM>”被重写。当然,Python依赖于约定来完成(许多)这样的事情,但是这种模式同样适用于它。你知道吗
因此,您的解决方案#1是不足为奇和合理的;而#2则依赖于一个很少使用的特性,该特性不适用于
super
或像C.start(self)
这样的手动向上调用。你知道吗相关问题 更多 >
编程相关推荐