Python 是否有仅限一次使用的对象的模式?

Python 是否有仅限一次使用的对象的模式?,python,c++,design-patterns,Python,C++,Design Patterns,假设您使用类Task2Do的对象表示要执行的任务。这些对象是可运行的,也就是说,它们有一个执行任务doTask的方法 另一方面,您有这些对象的队列(python中的示例): 您想运行所有待处理的任务: for t in pending: t.doTask() 可能会有人引入错误,使同一对象在pending队列中出现两次: pending = [a,a,c] 您可以保护您的代码: class Task2Do: def __init__(self, target, args):

假设您使用类
Task2Do
的对象表示要执行的任务。这些对象是可运行的,也就是说,它们有一个执行任务
doTask
的方法

另一方面,您有这些对象的队列(python中的示例):

您想运行所有待处理的
任务:

for t in pending:
    t.doTask()
可能会有人引入错误,使同一对象在
pending
队列中出现两次:

pending = [a,a,c]
您可以保护您的代码:

class Task2Do:
    def __init__(self, target, args):
        self._todo = target
        self._args = args
        self._done = False

    def doTask(self):
        if not self._done: # Protection against double execution
            self._todo(*self._args)
            self._done = True
我的问题是:这个设计模式有名字吗?我听说有些人已经实现了类似的调用C++中对象析构函数的方法。p>
你还知道其他类似的模式吗?

我不知道有什么设计模式可以在这里提供帮助,但是你的类Task2Do可以简化为:

class Task2Do:
    def __init__(self, target, args):
        self._todo = [target]
        self._args = args

    def doTask(self):
        while len(self._todo):
            todo = self._todo.pop(0):
            todo(*self._args)

这避免了
\u done
成员被意外地再次设置回
True

线程池模式允许您将可调用对象推送到数据容器,并在专用线程集上运行它们。线程池的一个优点是,不必在每次运行对象时都启动线程。运行对象时,将从容器中删除该对象,以便不再运行该对象。如果需要额外的逻辑来防止对象两次运行,可以将其添加到将对象添加到线程池的代码中,或者添加到在对象内部运行的代码中。

一个好的线程池库是CTPL,。

我能想到的最简单的方法是:

class Task2Do:
    def __init__(self, target, args):
        self._todo = target
        self._args = args

    def doTask(self):
        self._todo(*self._args)
        self._todo = lambda: None
        self._args = ()
看起来比国旗还干净。或者,让
self.\u todo
在第二次调用时抛出错误。您甚至可以通过将
self.\u todo
设置为
None
来实现这一点


不过,老实说,任务并不一定是课程。大多数情况下,仅仅拥有一个函数就更容易、更惯用。在这种情况下,您可以使用生成器一次性使用:

def task2do(target, *args, **kwargs):
    def iter_run_once():
        yield target(*args, **kwargs)
        raise ValueError("Multiple calls to one-time-use task")

    return iter_run_once().__next__

F = task2do(print, 1, 2, 3)

F()
#>>> 1 2 3

F()
#>>> Traceback (most recent call last):
#>>>   File "", line 14, in <module>
#>>>   File "", line 4, in iter_run_once
#>>> ValueError: Multiple calls to one-time-use task

)()

调用C++中的对象析构函数,听起来像是一个坏主意,要击败双执行。+ 1,因为您的答案提供了一个优雅的解决方案,“运行每个任务一次”问题,也就是说,在这个例子中提出的具体问题。不接受,因为不命名或描述一个对象只使用一次的模式。+1简洁明了!我认为类表示很有趣的一个例子是,一旦原子是进程(multiprocessing python库),您可能需要使用
Process
的子类来表示它们。但是,您可以在中间
目标
中实例化
过程。
def task2do(target, *args, **kwargs):
    def iter_run_once():
        yield target(*args, **kwargs)
        raise ValueError("Multiple calls to one-time-use task")

    return iter_run_once().__next__

F = task2do(print, 1, 2, 3)

F()
#>>> 1 2 3

F()
#>>> Traceback (most recent call last):
#>>>   File "", line 14, in <module>
#>>>   File "", line 4, in iter_run_once
#>>> ValueError: Multiple calls to one-time-use task
def task2do(target, *args, **kwargs):
    return (lambda: (yield target(*args, **kwargs)))().__next__