Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Python - функция сохранения с параметрами

Автор вопроса: CheezeyОтветов: 5

Я использую Tkinter для простой викторины. Есть несколько кнопок, по одной для каждого ответа, и я хотел бы запустить функцию checkAnswer с определенными параметрами при нажатии на нее.

Если бы я использовал что-то вроде следующего:

self.option1 = Button(frame, text="1842", command=self.checkAnswer(question=3, answer=2))

Затем он запускал checkAnswer и использовал то, что возвращал (ничего).

Есть ли простой способ сохранить параметры в конструкторе кнопок?

pythontkinter

Ответы

Ответ 1 · рейтинг 14 · Gareth Latty

Это именно то, для чего предназначен functools.partial():

>>> import functools
>>> print_with_hello = functools.partial(print, "Hello")
>>> print_with_hello("World")
Hello World
>>> print_with_hello()
Hello

partial() возвращает новую функцию, которая ведет себя так же, как и старая, но с любыми переданными вами аргументами, поэтому в вашем случае:

import functools

...

self.option1 = Button(frame, text="1842", command=functools.partial(self.checkAnswer, question=3, answer=2))

Ответ 2 · рейтинг 2 · jtmoulia

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

Например:

def makeCheckAnswer(self, **kwargs)
    return lambda: self.checkAnswer(**kwargs)

Это сделает инициализацию вашей кнопки:

self.option1 = Button(frame, text="1842", command=self.makeCheckAnswer(question=3, answer=2))

Ответ 3 · рейтинг 1 · Antti Haapala

Безусловно, проще всего просто использовать лямбда на месте

self.option1 = Button(frame, text="1842",
    command=lambda: self.checkAnswer(question=3, answer=2))

Хотя в подобных, но немного более сложных случаях вам действительно следует использовать фабрику функций, такую ​​как

def answerCheckerFactory(self, question, answer):
    def checker():
        return self.checkAnswer(question, answer)

    return checker

    ...
    self.option1 = Button(frame, text="1842",
        command=self.answerCheckerFactory(question=3, answer=2))

потому что это гарантирует, что вы передаете правильные аргументы (например, не quetsion (так в оригинале)); обратите внимание на отличие от functools.partial, которое позволяет вам неправильно набирать аргументы функции и получать исключение только при нажатии на кнопку;)

Кроме того, жесткое кодирование вопросов/ответов в коде кнопки кажется неправильным...

Ответ 4 · IT Ninja

Если у вас есть функции с определенными параметрами (которые не зависят от таких вещей, как text.get()), вы можете использовать для них обертки, что было бы самым простым способом сделать это, кроме функций лямбда. Например:

def option1wrapper():
    ClassName.checkAnswer(question=3,answer=2)
self.option1 = Button(frame, text="1842", command=option1wrapper)

Ответ 5 · Tlaloc-ES

Только вам нужно использовать лямбда-функцию, подобную этой

self.option1 = lambda: Button(frame, text="1842", command=self.checkAnswer(question=3, answer=2))

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы