Как остановить бесконечную рекурсию, когда объекты Python запускают обновления друг друга? - PullRequest
1 голос
/ 18 декабря 2010

Я использую 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, ООП, а также довольно плохо знаком с GUI-программированием. Я, наверное, действительно очень глуп, и / или упускаю из виду очевидное решение, но я до сих пор не могу понять, как не дать каждому ящику запускать обновление всех других ящиков после его обновления.

Заранее спасибо за ваши ответы - любая помощь будет принята с благодарностью.

1 Ответ

3 голосов
/ 18 декабря 2010

Самое простое решение для такого рода проблем, как правило, состоит в том, чтобы выяснить, нужно ли вам изменять содержимое объекта (в вашем случае это комбинированный список), а затем применять изменения, только если вы действительно что-то меняете.,Таким образом, вы будете распространять события обновления только в том случае, если они что-то делают.

Это должно выглядеть примерно так:

# '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)

Это довольно общий подход (даже некоторые системы сборки используют его).Основным требованием является то, что все действительно улаживается.В вашем случае это должно решиться немедленно.

...