【问题标题】:Python3: use exec() to create a functionPython3:使用 exec() 创建函数
【发布时间】:2019-09-04 14:01:44
【问题描述】:

我正在使用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否则。

【问题讨论】:

  • 这看起来是个糟糕的主意。
  • 坏主意。不要这样做。
  • 我必须尝试一下,否则我将需要复制和粘贴很多使我的项目变大的函数:(

标签: python python-3.x tkinter windows-7 exec


【解决方案1】:

这里绝对没有必要使用exec()eval()

  • 函数不必按顺序命名。您也可以将函数对象存储在循环变量中,并使用该循环变量来创建 tkinter 钩子。
  • 您可以使用不带 exec 的绑定参数创建函数,使用闭包,或者仅通过在 lambda 函数或 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=... 部分将当前循环值绑定为lambda 创建的新函数对象的point 参数的默认值。当不带参数调用该函数时(就像单击按钮时所做的那样),新函数使用当时分配给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()函数会返回一个新函数,用作按钮命令。

【讨论】:

  • 哇,谢谢老兄!拉姆达太棒了!虽然我不使用它:) [因为我很喜欢 lambda]
  • TIL 你可以从函数中返回函数。智能且适用于特定场景。
  • 这在我做下一个项目时很有用(sudoko)
【解决方案2】:

免责声明:我尚未对此进行测试。

使用字典来存储你的所有函数,例如:

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(),除非你绝对知道它有什么安全问题,你知道该产品不会在另一台机器上使用,或者你真的别无选择。

【讨论】:

  • 感谢您的回答,但我的意思是我需要创建很多功能,上面的答案有效,如果我可以投票,我可能会投票给你,但我可以't :)
  • 正如我所说,我在 tkinter 中做了很多按钮 :)
猜你喜欢
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
相关资源
最近更新 更多