python - 将多个列表收集在一起

标签 python events python-3.x

我正在创建一个游戏,它具有键盘事件和一个可以在其上注册函数的事件系统,并且需要返回两个列表(任何大小):一个游戏时间事件列表和一个列表实时事件(按此顺序)。然后事件运行者将

我正在重构代码来做到这一点。在之前的系统中,事件会手动将其事件与主游戏时间/实时事件队列合并。

我正在尝试重构当按下/释放按键时触发所有事件的代码。当前代码:

class KeyReleaseEventRunner
    GameEvents = []
    RealEvents = []        

    def __call__(self):
        """Run all relevant events."""

        # Run key-specific key release events
        KeyReleaseEvent[self.key]()

        # Run key-specific key toggle events
        KeyToggleEvent[self.key](False)

        # Run generic key release events
        KeyReleaseEvent(self.key)

        # Run generic key toggle events
        KeyToggleEvent(self.key, False)

我的问题是如何合并每个函数的所有事件。

是否有更简单、可读的方法来做到这一点?:

    def __call__(self):
        """Run all relevant events."""

        # Run key-specific key release events
        g_events, r_events = KeyReleaseEvent[self.key]()
        self.GameEvents.extend(g_events)
        self.RealEvents.extend(r_events)

        # Run key-specific key toggle events
        g_events, r_events = KeyToggleEvent[self.key](False)
        self.GameEvents.extend(g_events)
        self.RealEvents.extend(r_events)

        # Run generic key release events
        g_events, r_events = KeyReleaseEvent(self.key)
        self.GameEvents.extend(g_events)
        self.RealEvents.extend(r_events)

        # Run generic key toggle events
        g_events, r_events = KeyToggleEvent(self.key, False)
        self.GameEvents.extend(g_events)
        self.RealEvents.extend(r_events)

        # Events must maintain sorted-ness
        self.GameEvents.sort()
        self.RealEvents.sort()

我不想在KeyReleaseEventRunner上创建方法(这种情况在其他几个地方也有,并且经常使用局部变量而不是GameEvents/RealEvents)。

更一般地说,是否有更好的解决方案让这些函数返回两个列表?

可以区分 g_events 和 r_events 中的事件。

编辑:

为了消除有关可调用和可索引对象的任何混淆:

值得注意的是,Event 的实例是注册函数的接口(interface),并且在调用时调用所有已注册的对象。 KeyToggleEventKeyReleaseEvent(以及 KeyPressEvent)是 Event 子类的实例,其他模块可以通过它们注册特定于按键的事件(通过注册到 KeyReleaseEvent[key]),以及非特定于按键的事件(通过注册到 KeyReleaseEvent)。

最佳答案

我想知道索引和调用的组合的原因是它似乎使您的界面过于复杂。这可能不是您想听到的,但我忍不住觉得您最好使用关键字参数而不是索引来指定事件子集。然后,您可以创建参数列表和对象列表,并迭代它们。像这样的事情:

arg_list = [{'key':self.key, 'foo':False}, {'key':self.key}, ... ]
handlers = [KeyReleaseEvent, KeyToggleEvent, ...]
for handler, args in zip(arg_list, handlers):
    g_events, r_events = handler(*args)
    self.GameEvents.extend(g_events)
    self.RealEvents.extend(r_events)
self.GameEvents.sort()
self.RealEvents.sort()

或者更简洁:

gevents_revents = [handler(*args) for handler, args in zip(arg_list, handlers)]
all_gevents, all_revents = zip(*gevents_revents)
self.GameEvents.extend(e for sublist in all_gevents for e in sublist)
self.RealEvents.extend(e for sublist in all_revents for e in sublist)

当然,您仍然可以使用当前的设置执行类似的操作。但我担心这会有点不太优雅。

我还认为您应该考虑为事件队列使用不同的数据结构。您是否考虑过使用优先级队列,而不是简单的列表,例如 heapq 提供的队列。 ?这将使您避免重复 (O(n log n)) 排序。单个插入和删除的时间复杂度为 O(log n),这比使用列表的简单方法 (O(n)) 更好,但比更仔细的方法 (O(1)) 更差。实际上,您会随着时间的推移分散工作,因为单个项目会从队列中删除,而不是一次按单一排序完成所有工作。但你仍然会得到 O(n) 合并!

这是否是正确的方法取决于您自己的情况。 (例如,如果您需要查看将来事件的顺序,这不是最好的方法。)如果您感兴趣,我可以写更多相关内容,但基本思想是您可以使用 heapq.heapify (O(n)) 而不是 sort (O(n log n))。

arg_list = [{'key':self.key, 'foo':False}, {'key':self.key}, ... ]
handlers = [KeyReleaseEvent, KeyToggleEvent, ...]
for handler, args in zip(arg_list, handlers):
    g_events, r_events = handler(*args)
    self.GameEvents.extend(g_events)
    self.RealEvents.extend(r_events)
heapq.heapify(self.GameEvents)
heapq.heapify(self.RealEvents)

然后将最高优先级的项目从队列中取出:

next_game_event = heapq.heappop(self.GameEvents)

关于python - 将多个列表收集在一起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10656771/

相关文章:

python - 属性错误 : 'Cycler' object has no attribute 'change_key'

python - 如何在 PyQt5 中拥有动态字段?

python - 使用 docker 和 GPU 进行 Pycharm 调试

python - 如何在 python3 中使用 ldap3 绑定(bind)(验证)用户

javascript - 如何注册鼠标悬停/输入事件以滚动过去(跳过)元素?

Javascript 触发事件

javascript - 事件虽然注册一次,但事件被触发多次

python-3.x - 无法使 Python 3.7 在 Ubuntu 18.04 中工作

python - 使用 boto3 时 S3 连接超时

python ,XPath : Find all links to images