PySide2 调用错误的回调函数

PySide2 calls wrong callback function

考虑以下 PySide2 程序(python 版本 3.8.6 和 PySide2 版本 5.15.1):

from PySide2.QtWidgets import QApplication, QLineEdit

def setup(w, sigs):
    for name, f in sigs:
        getattr(w, name).connect(lambda *args: f(*args))

app = QApplication()
win = QLineEdit()

setup(win, [("textChanged",   lambda *args: print("  text", args)),
            ("returnPressed", lambda *args: print("return", args))])

win.show()
app.exec_()

这是我输入“asdf”并按回车键时的输出:

return ('a',)
return ('as',)
return ('asd',)
return ('asdf',)
return ()

我希望这是

  text ('a',)
  text ('as',)
  text ('asd',)
  text ('asdf',)
return ()

为什么PySide要在QLineEdit上连接后面的回调函数?如果我将 setup 函数更改为

def setup(w, sigs):
    for name, f in sigs:
        getattr(w, name).connect(f)

它按预期工作。以下也适用:

def const(f):
    return lambda *args: f(*args)

def setup(w, sigs):
    for name, f in sigs:
        getattr(w, name).connect(const(f))

这与 PySide 无关,但与 闭包

lambda 的范围在创建它的函数内,因此当您在循环中创建多个 lambda 时,任何未在其参数中引用的变量都是 last 该范围内已知变量的值。在您的情况下,f 始终是列表的最后一个函数。

顺便说一句,在你的情况下,你让事情变得比他们应该的更复杂:只需连接到函数,绝对不需要创建 另一个 lambda:

def 设置(w, 信号):
    对于名字,f 在 sigs 中:
        getattr(w, 名字).<b>connect(f)</b>