0

我目前正在开发一个模块,该模块允许用户通过创建任务对象的实例(我的模块提供一个任务类)来构建任意任务网络模型(用于离散事件模拟)。除其他外,任务包含描述其完成效果的逻辑,例如不同任务的启动。这样,任务类的一个实例可以引用一个或多个其他实例,具有循环引用/相互递归的可能性。

这是我的代码的一个极其简化的版本:

任务模块.py

class Task(object):
    def __init__(self, name, effect):
        self.name = name
        self.effect = effect

def execute(task):
    task.effect()

任务测试.py

task1 = task("Do the first thing", execute(task2))
task2 = task("Do the second thing", execute(task3))
task3 = task("Do the third thing", execute(task1))

这个实现的问题是我在定义 task2 和 task3 之前就引用了它们。如果我可以排除循环引用,那将不会是世界末日——这只是重新安排对象实例化顺序的问题——但我相信我应该适应这种可能性。我已经考虑了几个潜在的解决方法——大多数会涉及要求用户间接引用任务(即通过一些唯一的标识符值)——但我想知道是否有一个更优雅的解决方案,它涉及一种巧妙的抽象形式。

确保实例化任务/生成任务网络的过程(如 TaskTest.py 中所示)尽可能简单易行是该项目的首要任务,因为这是我模块的用户将花费的大部分时间时间做。

我尝试搜索,但似乎大多数关于相互递归/循环引用主题的问题都涉及函数或类而不是实例。

4

3 回答 3

2

所以,我认为这里的问题是名称和对象被混为一谈。我可能会使用一种结构,其中任务对象组织在字典中,字符串或枚举用作键。这样,您可以在分配名称之前引用它们。

class TaskManager:
    def __init__(self, tasks=None):
        self.tasks = tasks or {}

    def register(self, name, task):
        self.tasks[name] = task

    def execute(self, name):
        self.tasks[name].effect()
于 2017-06-02T18:48:34.470 回答
1

您需要某种占位符对象来表示其依赖关系未知的任务。然后你可以做

task1 = Task("Do the first thing", [Placeholder()])
task2 = Task("Do the second thing", [execute(task1)])
task3 = Task("Do the third thing", [execute(task2)])
task1.add_dependency(task3)
task1.remove_placeholders()

它需要Task("...", [Placeholder()])而不是Task("...", [])因为后者代表一个没有依赖关系的任务,你也希望能够表达它。

于 2017-06-02T18:37:26.810 回答
1

实现此目的的一种方法是创建一个 TaskList 对象来管理任务。实现将取决于您,但本质上您希望拥有一个按顺序执行的任务列表。如果某个任务产生进一步的工作(即,非无返回),那么这个结果任务将被附加到列表中。

显然,这很容易产生一个无限的过程,所以你可能想考虑你想如何处理这个,但这更多地涉及到 UI 设计。

于 2017-06-02T18:55:58.563 回答