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__