Python3: используйте exec () для создания функции - PullRequest
0 голосов
/ 14 апреля 2019

Я использую tkinter для создания приложения, и в настоящее время я сделал много кнопок, поэтому мне нужно связать все кнопки разными командами, я хотел бы использовать exec() для создания функций.

strategy=None
exec("global commandbutton"+str(len(strategicpoint)+1)+"\ndef commandbutton"+str(len(strategicpoint)+1)+"():\n\tglobal strategy\n\tstrategy="+str(len(strategicpoint)))
commandline=eval('commandbutton'+str(len(strategicpoint)+1))
imgx=tk.Button(win,image=towert,command=commandline)

для более чистых решений:

global commandbutton{...}
def commandbutton{...}():
    global strategy
    strategy={...}

Я хочу, чтобы мой код выполнялся, как описано выше, и он запускается, но позже я вызываю команду и проверяю ее на print(strategy), (я нажал кнопку / вызвал команду)печатает None, когда я хочу напечатать что-то еще.

Ответы [ 2 ]

2 голосов
/ 14 апреля 2019

Здесь абсолютно не нужно использовать exec() или eval().

  • Функции не должны называться последовательно. Вы также можете хранить функциональные объекты в переменной цикла и использовать эту переменную цикла для создания хука tkinter.
  • Вы можете создавать функции со связанным параметром без exec, используя замыкание или просто связывая параметр в лямбда-функции или functools.partial().

Так что если у вас есть цикл с возрастающим значением strategicpoint, я бы просто сделал это:

def set_strategy(point):
    global strategy
    strategy = point

buttons = []
for strategicpoint in range(1, number_of_points + 1):
    imgx = tk.Button(win, image=towert, command=lambda point=strategicpoint: set_strategy(point))
    buttons.append(imgx)

Часть lambda point=... связывает текущее значение цикла как значение по умолчанию для аргумента point нового функционального объекта, который создает lambda. Когда эта функция вызывается без аргументов (как это было бы сделано при нажатии кнопки), тогда новая функция использует целочисленное значение, которое было присвоено strategicpoint в то время, чтобы вызвать set_strategy(point).

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

def create_strategy_command(strategypoint):
    def set_strategy():
        global strategy
        strategy = strategypoint
    return set_strategy

затем при создании кнопок используйте:

imgx = tk.Button(win, image=towert, command=create_strategy_command(strategicpoint))

Обратите внимание, что вызов функции create_strategy_command() возвращает здесь новую функцию, используемую в качестве команды кнопки.

0 голосов
/ 14 апреля 2019

Отказ от ответственности: я не проверял это.

Используйте словарь для хранения всех ваших функций, например:

option = "default"
def change_option(target):
    global option
    option = target

def f1():
    print("foo")
def f2():
    print("bar")

my_functions = {
    "select1": f1,
    "select2": f2
    "default": None
    }

imgx=tk.Button(win,image=towert,command=my_functions[option])  # None
swapper = tk.Button(win, image=towert, lambda: change_option("select2")) # button to change the command if you want it
imgx=tk.Button(win,image=towert,command=my_functions[option]) # print("bar")
change_option("select1")
imgx=tk.Button(win,image=towert,command=my_functions[option]) # print("foo")

Возможно, вы могли бы обойтись без использования словаря, нона мой взгляд, это довольно чисто.Никогда не используйте exec () или eval (), если вы абсолютно не знаете, какие у него проблемы с безопасностью, вы не знаете, что продукт не будет использоваться на другой машине, или у вас действительно нет другого выбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...