Как передать аргумент в функцию, которая вызывается без скобок? - PullRequest
1 голос
/ 20 января 2020

Это пример кода из pynput документации . Он в основном печатает клавишу, которую вы нажимаете.

from pynput import keyboard

def on_press(key):
    print('You pressed {}'.format(key))

    if key == keyboard.Key.esc:
        return False

with keyboard.Listener(
    on_press=on_press) as listener:
listener.join()

Мне нужно передать аргумент функции on_press, но она вызывается без скобок. Я не понимаю, почему и что это делает. В идеале это то, что я хотел бы заставить работать:

from pynput import keyboard

def on_press(key, addition):
    print('You pressed {}, {}'.format(key, addition))

    if key == keyboard.Key.esc:
        return False

string = 'congrats!'

with keyboard.Listener(
    on_press=on_press(key, string)) as listener:
listener.join()

Ответы [ 3 ]

2 голосов
/ 20 января 2020

Это не называется без скобок; это передается в качестве аргумента без вызова. Параметр on_press должен быть функцией, которая будет вызываться классом Listener; код для этого класса будет иметь что-то вроде on_press(key) для вызова функции, которую вы предоставляете, с одним аргументом.

Поскольку передаваемая вами функция будет вызываться с одним аргументом, вам нужно предоставить функцию, которая (1) принимает key в качестве аргумента и (2) вызывает on_press(key, string) с этими двумя аргументами. Одним из решений является использование ключевого слова lambda:

on_press_func = lambda key: on_press(key, string)
with keyboard.Listener(on_press=on_press_func) as listener:
    listener.join()

Вы также можете написать лямбда-функцию таким образом, чтобы сразу связать значение string вместо закрытия над ним :

on_press_func = lambda key, string=string: on_press(key, string)
2 голосов
/ 20 января 2020
with keyboard.Listener(on_press=on_press) as listener:

Это на самом деле не вызывает on_press, оно передает его keyboard.Listener. (Python функции являются первоклассными, то есть их можно передавать.) Затем объект Listener вызовет его позже.

Вы можете использовать функцию более высокого порядка, чтобы установить addition:

def outer(addition):
    def on_press(key):
        print('You pressed {}, {}'.format(key, addition))
        ...
    return on_press

with keyboard.Listener(on_press=outer('congrats!')) as listener:
    listener.join()

Частичное также отлично работает.

1 голос
/ 20 января 2020

Вы можете использовать partial:

from pynput import keyboard
from functools import partial

def on_press(addition, key):
    print('You pressed {}, {}'.format(key, addition))

    if key == keyboard.Key.esc:
        return False

string = 'congrats!'
p_on_press = partial(on_press, string)

with keyboard.Listener(
    on_press=p_on_press) as listener:
    listener.join()
...