如何防止Python对象相互触发更新时的无限递归?

1 投票
1 回答
807 浏览
提问于 2025-04-16 08:42

我正在使用PyGTK和gtk.Assistant这个小部件。在一个页面上,我有六个下拉框,最开始这六个下拉框里都是相同的内容(六个数字)。当用户在其中一个下拉框中选择了一个数字后,这个数字就不应该出现在其他五个下拉框中(除非它在原始列表中是重复的)。所以我想要不断更新这些下拉框的内容。

我尝试了以下的方法(这里只是一些代码片段),但是(当然了……)一旦这个过程被触发,就会陷入无限循环:

# 'combo_list' is a list containing the six comboboxes

def changed_single_score(self, source_combo, all_scores, combo_list, indx_in_combo_list):
    scores = all_scores.split(', ')
    for i in range(6):
        selected = self.get_active_text(combo_list[i])
        if selected in scores:
            scores.remove(selected)

    # 'scores' only contains the items that are still available
    for indx in range(6):
        # don't change the box which triggered the update
        if not indx == indx_in_combo_list:
            # the idea is to clear each list and then repopulate it with the
            # remaining available items
            combo_list[indx].get_model().clear()

            for item in scores:
                combo_list[indx].append_text(item)

            # '0' is appended so that swapping values is still possible
            combo_list[indx].append_text('0')

上面的函数是在其中一个下拉框发生变化时被调用的:

for indx in range(6):
    for score in self.selected['scores'].split(', '):
        combo_list[indx].append_text(score)

    combo_list[indx].connect('changed', self.changed_single_score, self.selected['scores'], combo_list, indx)

也许我应该提一下,我对Python、面向对象编程(OOP)和图形用户界面编程(GUI)都还很陌生。我可能在这里显得很傻,或者忽视了明显的解决方案,但到目前为止,我还没有找到如何在一个下拉框更新后,阻止它触发其他下拉框的更新。

提前感谢你的回复——任何帮助都会非常感激。

1 个回答

3

解决这类问题最简单的方法通常是先弄清楚你是否需要更改对象的内容(在你的例子中是下拉框),然后只有在你真的要改变某些东西时才去应用这些更改。这样,你就只会在有实际变化时才触发更新事件。

这看起来应该像这样:

# '0' is appended so that swapping values is still possible
items = [item for item in scores] + ['0']

for indx in range(6):
    # don't change the box which triggered the update
    if not indx == indx_in_combo_list:
        # I'm not 100% sure that this next line is correct, but it should be close
        existing_values = [model_item[0] for model_item in combolist[indx].get_model()]

        if existing_values != items:
            # the idea is to clear each list and then repopulate it with the
            # remaining available items
            combo_list[indx].get_model().clear()
            for item in items:
                combo_list[indx].append_text(item)

这是一种比较通用的方法(甚至一些构建系统也会用到)。主要的要求是事情确实要稳定下来。在你的情况下,它应该会立即稳定。

撰写回答