创建幂等方法的Pythonic方法

2024-04-18 01:51:15 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们用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:是自修改代码


Tags: 方法函数代码selfreturnifdefcode
2条回答

您可以创建一个函数来执行以下操作:

import inspect

def exec_once(self):
    name = inspect.currentframe().f_back.f_code.co_name
    setattr(self, name, lambda: None)


class C:
    def start(self):
        print("Start!")
        exec_once(self)


class C2:
    def start(self):
        super().start()
        print("Start 2!")
        exec_once(self)

注意,在子类中,必须显式地添加exec_once(self)。你知道吗

在派生类中重写的内容可能不是公共接口的元素,而是实现该接口的部分的某个内部函数的想法称为non-virtual interface pattern。当一个公共方法有几个这样的部分时,它通常被称为“模板方法”。术语来自C++(最初来自Simula),在这里可以执行这样的模式,因为只有{< CD1> }函数可以“EEM>”被重写。当然,Python依赖于约定来完成(许多)这样的事情,但是这种模式同样适用于它。你知道吗

因此,您的解决方案#1是不足为奇和合理的;而#2则依赖于一个很少使用的特性,该特性不适用于super或像C.start(self)这样的手动向上调用。你知道吗

相关问题 更多 >