Передать дополнительные аргументы с помощью функции обратного вызова

В следующем примере (взятом отсюда: http://urwid.org/tutorial/index.html) показано, как передать значения ключей в функцию обратного вызова show_or_exit,

import urwid

def show_or_exit(key):
    if key in ('q', 'Q'):
        raise urwid.ExitMainLoop()
    txt.set_text(repr(key))

txt = urwid.Text(u"Hello World")
fill = urwid.Filler(txt, 'top')
loop = urwid.MainLoop(fill, unhandled_input=show_or_exit)
loop.run()

Как я могу передать другой аргумент show_or_exit с этим обратным вызовом, который зависит от состояния системы, это будет что-то вроде этого?

...: param_val = 4
...:
...: def my_fun():
...:     #do something
...:     return param_val
...:
...: def show_or_exit(key, param_val):
...:     if key in ('q', 'Q'):
...:         raise urwid.ExitMainLoop()
...:     txt.set_text(repr(key))
...:     do_something(param_val)
...:
...: txt = urwid.Text(u"Hello World")
...: fill = urwid.Filler(txt, 'top')
...: loop = urwid.MainLoop(fill, unhandled_input=show_or_exit)
...: loop.run()

1 ответ

Решение

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

Для небольших программ, таких как в этом примере, одним из методов может быть использование одного глобального объекта, хранящего состояние:

import urwid
from functools import partial


class State(object):
    param1 = 1
    param2 = 'ola'

    def __repr__(self):
        return 'State(param1={}, param2={})'.format(self.param1, self.param2)


def show_or_exit(app_state, key):
    if key in ('q', 'Q'):
        raise urwid.ExitMainLoop()
    app_state.param1 += 1
    txt.set_text('key: {!r} state: {!r}'.format(key, app_state))


txt = urwid.Text(u"Hello World")
fill = urwid.Filler(txt, 'top')
app_state = State()
callback = partial(show_or_exit, app_state)
loop = urwid.MainLoop(fill, unhandled_input=callback)
loop.run()

Я сохранил этот пример минимальным для целей иллюстрации, но этот класс State выиграл бы ОЧЕНЬ много от использования библиотеки attrs. Настоятельно рекомендуется!:)

Для более сложных программ я бы предложил создавать собственные виджеты, поддерживающие события обратного вызова, и управлять состоянием отдельно: вы можете увидеть пример реализации этого в этой пасьянсе.

Другие вопросы по тегам