Итак, смотрю я, что тут целый раздел пустой... Вот и решил я немного подтолкнуть его в нужном направлении. А за одно и посмотрю, что за люди здесь собрались... Может кого-нить в команду себе присмотрю... Скоро собирать буду... Даже спонсор есть... :-)

Пишу я на PyQt4 довольно сложную штуку (умолчу какую именно -- это сейчас не имеет значения). И довольно часто сталкиваюсь с ситуацией, когда нужно выполнить небольшую цепь действий по сигналу. Всё Ok, но писать для этого функцию типа:
class c(QObject):
    ...
    def __init__(self...):
        ...
        self.connect(self, SIGNAL("signal()", self._signal_func)
        ...
    def _signal_func(self):
        work1()
        work2()
        work3()
Неудобно, блин.

Такой вариант не катит:
class c(QObject):
    ...

    def __init__(self...):
        ...
        def signal_func():
            work1()
            work2()
            work3()
        self.connect(self, SIGNAL("signal()", signal_func)
        ....
Потому, что после выполнения главной функции (в данном случае __init__) вызывается деструктор signal_func (по довольно странным причинам, ведь в QMetaObject должна была остоваться ссылка... ну да ладно.) и, соответственно, disconnect.

Можно, конечно, сделать так:
self.connect(self, SIGNAL("signal()", work1)
self.connect(self, SIGNAL("signal()", work2)
self.connect(self, SIGNAL("signal()", work3)
Но тогда нам приходится учитывать разные нитивые коллизии. Это не решение.

Я нашёл очень своеобразный и спорный выриант (уже не помню где, не сам ли? А может и в доках проскочило... не важно.):
class c(QObject):
    ...

    def __init__(self...):
        ...
        self.connect(self, SIGNAL("signal()", lambda self: work1() or work2() or work3())
        ....
Проще? ИМХО да. Сначала не очень понятно...
И, как по какой-то магии, деструктор для лямбды не вызывается. Кто знает почему? Я не нашёл решение (впрочем не особо-то и искал... но искал.).
Нужно только знать вывод work'ов (в данном случае у нас все выводят False), и всегда можно составить то, что нужно.

Например, если work2() вернёт True, то нужно, всего-лишь добавить not...
Если у нас неизвестен вывод work2() (1 и 2 == False), то как вам такое решение?:
lambda self: ((work1() or work2()) and work3()) or work3()
Вообще, это называется функциональным программированием... Но это не статья...

Если нужно выполнить что-нить вроде self.var = val (в лямбде этого нельзя), то setattr(self, "var", val) замечательно справится... Также неплохо работают globals() и locals() (setdefault).

Меня интересует, это только я такой долблнутый на всю бошку, или есть более нормальные решения?

P.S. Интересно, а сколько человек, увидев тему подумали про Half-Life?
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Не понятно, в чем неудобства то?
Что это за цепочка действий, какого рода эти действия?
Мож так
class c(QObject):
    ...
    def __init__(self...):
        ...
        slef.works = [work1, work2, work3]
        self.connect(self, SIGNAL("signal()", self._signal_func))
        ...
    def _signal_func(self):
        for work in self.works:
            work()
В этом-то всё и дело, что я не хочу создавать лишний метод для класса.
Но мысль очень интересная... скорее в следующем виде:
works = [work1, work2, work3]
self.connect(self, SIGNAL("signal()", lambda : map(lambda w: w(), works)))
Блин, так гораздо лучше. Будем использовать...

Обратите внимание на то, что lambda получит аргументы сигнала.
Если нужно их обработать, то мой вариант больше подходит.
Например, вот кусок реального кода:
        self.connect(self.View, SIGNAL("pressed(QModelIndex)"),
                lambda Index: self.Stack.setCurrentWidget(self.VisibleModules[Index.row()]) \
                        or self.CaptionLabel.setText(self.VisibleModules[Index.row()].Name) \
                        or self.emit(SIGNAL("currentModuleChanged(QWidget)"), self.VisibleModules[Index.row()]))
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Вместо
lambda: map (lambda w: w(), works)

можно попробовать
lambda: [lambda w: w() for w in works]

(вместо фигурных скобок {}, конечно же, квадратные

Last edited SatAMMSKEMSK0NovE_November+0300RNovAMMSK

Нет, видимо, форум пытается отрендерить квадратные скобки, как bbcode. Можно:
* попробовать переключиться на mardown
* офоормлять код тэго CODE (в bbcode синтаксисе) или 4-мя отступами (в markdown)
Да, в смежной теме Shiza хорошо показал это. Выигрыш действительно серьёзный.

Да и вообще, сегодня я бы многое здесь по-другому писал... Все мы учимся!
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
> В этом-то всё и дело, что я не хочу создавать лишний метод для класса.
> works =
> self.connect(self, SIGNAL("signal()", lambda : map(lambda w: w(), works)))

Расстреливал бы за такой код.
Если бы ты создал отдельный метод и дал ему нормальное имя у тебя бы был самодокументируемый код, а придется сидеть и думать, что у тебя там за лямбда в лямбде. Такой код читается очень тяжело, а зачем его городить? Что бы сэкономить несколько строк?
Первый, второй и третий варианты, причем третий именно как ты оформил, а не в цикле я стаю самыми лучшими. Если в классе много методов (>=10) то стоит задуматься писать ли еще один, поэтому первый вариант может быть и не приемлем, но это больше от предпочтений зависит.
Я сейчас стал бороться с кашей методов простым способом (интуитивно я его и раньше использовал, но сейчас больше официальности в нём) - группировка методов (свойства, публичные, внутренний/скрытые, обработчики событий и т.п.), а так же описание их сущности в комментарии в одной строке (или нескольких, если на поговорить с самим собой пробило).

..bw
Не знаю, bw, мне хватает комментариев, которые я обычно не забываю добавлять.
Городоть такой код стоит для того, чтобы сделать более читаемым (!) сам класс, а не конкретный его метод. И делать это надо не бездумно типа всё скопом только так, а только интуитивно понятные вещи.
Просто довольно часто мои классы просто перегружены, что никакая группировка не спасает. Мне было бы интересно взглянуть на твой метод группировки методов, может действительно я до чего-то недопёр...
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.