将参数传递给回调

Passing an argument to a callback

我在使用键盘模块 add_word_listener 时遇到了一些麻烦。如果我有一个接受回调作为参数的函数,我该如何将参数传递给回调?例如,这里是最小可重现代码:

import keyboard

stopKey = "Windows"


def test(arg):
    print(arg)

keyboard.add_word_listener("hi", test("Hello World!"))

running = True
while running:
    if keyboard.is_pressed(stopKey):
        running = False

add_word_listener 是一个函数,它有 2 个必需的参数、它侦听的文本和一个回调。在键盘文档页面上,回调参数被描述为“每次键入单词时都会调用的无参数函数”。那么这是否意味着我无法将参数传递给 add_word_listener 中的 test 函数?该代码仅在我们删除参数并且只有 keyboard.add_word_listener("hi", test) 时才有效。如果这是唯一的方法,那么有没有更好的方法在这里传递一个带参数的函数而不是创建很多特定的函数?即而不是创建像

这样的函数
def printhi():
    print("hi")
    
def printhello():
    print("hello")

每次我想使用add_word_listener?

martineau 提到 lambda 作为解决方案

keyboard.add_word_listener("hi", lambda: test("Hello World!"))

另一个是functools.partial

keyboard.add_word_listener("hi", functools.partial(test, "Hello World!"))

您甚至可以使用 __call__ 方法而不是函数

创建 class
class Test:
    def __init__(self, arg):
        self.arg = arg
    def __call__(self):
        print(self.arg)

keyboard.add_word_listener("hi", Test("Hello World!"))

如果您想保留一些额外的状态,最后一个很有用。就像 made-up 的例子,如果你想记录回调发生的时间,你可以做

class Test:
    def __init__(self, arg):
        self.arg = arg
    def __call__(self):
        self.called_at = time.time()
        print(self.arg)

test = Test("Hello world")
keyboard.add_word_listener("hi", test)

我喜欢上面的两种解决方案。如果 lambda 表达式吓到你,你还可以使用一个额外的函数。

def my_callback():
    test("hello")

keyboard.add_word_listener("hi", my_callback)

您甚至可以像这样编写更通用的代码:

def add_my_word_listener(word, callback_word):
    def my_callback():
        test(callback_word)
    keyboard.add_word_listener(word, my_callback)

add_my_word_listener("hi", "hello")
add_my_word_listener("ciao", "goodbye")