【问题标题】:Mutual recursion between objects in PythonPython中对象之间的相互递归
【发布时间】:2017-11-04 05:46:22
【问题描述】:

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

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

TaskModule.py

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

def execute(task):
    task.effect()

TaskTest.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 中所示)的过程尽可能简单易行是该项目的首要任务,因为这是我模块的用户将花费的他们大部分时间都在做。

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

【问题讨论】:

  • 你能把你的问题说得更清楚些吗?
  • 基本上,我怎样才能允许用户以最简洁的方式创建具有交叉依赖关系的任务实例?如果可能,每个任务使用一行代码,如 TaskTest.py 中所示。

标签: python cyclic-reference mutual-recursion cyclic-dependency forward-reference


【解决方案1】:

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

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()

【讨论】:

  • 我之前一直在考虑这些方面的东西,但你解释它的方式最终让一切都成功了。谢谢。
【解决方案2】:

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

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("...", []),因为后者代表一个没有依赖的任务,你也希望能够表达。

【讨论】:

  • 嗯...是的,我知道它是如何工作的。但是,我的目标(出于用户体验的考虑)是将任务实例化的过程保留为一行代码。有什么办法吗?
  • @mcman 我相信这基本上是不可能的。每个任务构造器只能引用已经被命名的任务,因此要构造一个循环,必须有一种方法来命名一个依赖关系未知的任务,然后再插入它的依赖关系。
【解决方案3】:

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

显然,这很容易产生无限过程,因此您可能需要考虑如何处理这个问题,但这更多地涉及到 UI 设计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多