简体   繁体   English

Python3:使用 exec() 创建函数

[英]Python3: use exec() to create a function

I am using tkinter to create an app and currently I made a lot of buttons so I need to bind all buttons with different command, I will like to use exec() to create functions.我正在使用 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)

for cleaner solutions:对于更清洁的解决方案:

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

I want my code run like above and it runs, but later I call the command and test to print(strategy) , (I have clicked the button/invoked the command) it prints None when I want it to print something else.我希望我的代码像上面一样运行并运行,但后来我调用命令并测试print(strategy) ,(我点击了按钮/调用了命令)当我想要它打印其他东西时它打印None

There is absolutely no need to use exec() or eval() here.这里绝对不需要使用exec()eval()

  • Functions don't have to be named sequentially.函数不必按顺序命名。 You can store function objects in a loop variable too and use that loop variable to create a tkinter hook.您也可以将函数对象存储在循环变量中,并使用该循环变量来创建 tkinter 钩子。
  • You can create functions with a bound parameter without exec , using a closure, or just by binding the parameter in a lambda function or functools.partial() .您可以使用没有exec的绑定参数创建函数,使用闭包,或者仅通过在 lambda 函数或functools.partial()绑定参数。

So if you have a loop with an incrementing strategicpoint value, I'd just do this:因此,如果您有一个具有递增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)

The lambda point=... part binds the current loop value as a default value for the point argument of the new function object that lambda creates. lambda point=...部分将当前循环值绑定为lambda创建的新函数对象的point参数的默认值。 When that function is called without arguments (as would be done when clicking the button), then the new function uses the integer value that was assigned to strategicpoint at the time, to call set_strategy(point) .当该功能被称为不带参数(如将点击该按钮时完成),那么新的函数使用被分配到整数值strategicpoint的时候,打电话给set_strategy(point)

You can also use a closure, a local variable in an outer function, that an inner function makes use of.您还可以使用内部函数使用的闭包,即外部函数中的局部变量。 Nested, inner functions inside an outer function are created each time you call the outer function, so they are separate from other function objects created by the same outer function:每次调用外部函数时都会在外部函数内创建嵌套的内部函数,因此它们与由同一外部函数创建的其他函数对象分开:

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

then when creating your buttons, use:然后在创建按钮时,使用:

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

Note that calling the create_strategy_command() function returns a new function here, used as the button command.请注意,调用create_strategy_command()函数会在此处返回一个新函数,用作按钮命令。

Disclaimer: I haven't tested this.免责声明:我没有测试过这个。

Use a dictionary to store all your functions, as such:使用字典来存储您的所有函数,例如:

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")

You could probably get by without using a dictionary, but in my opinion this is rather clean.你可能可以不使用字典,但在我看来这是相当干净的。 Don't ever use exec() or eval(), unless you absolutely know what security concerns it has, you know the product wont be used on another machine, or you really don't have another choice.永远不要使用 exec() 或 eval(),除非你完全知道它有什么安全问题,你知道该产品不会在另一台机器上使用,或者你真的别无选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM