Python动态函数生成

4 投票
5 回答
679 浏览
提问于 2025-04-16 21:26

我正在使用PyQt,想根据一个字符串列表来创建一个菜单。

问题是,当我想调用'addAction'时,它需要一个回调函数(针对每个字符串),而这个函数不能接受任何参数。

对于简单的菜单来说,这样是没问题的,比如:

menu.addAction("Open", self.open)
menu.addAction("Exit", self.quit)

但是,我想只用一个函数,并把'动作字符串'作为参数传进去。

我在想Python能不能做到这一点:

def f(x, y):
    print x + 2*y



# These 2 variables are of type: <type 'function'>
callback1 = f
callback2 = f(x=7, *)
# NB: the line above is not valid python code.
# I'm just illustrating my desired functionality

print callback1(2,5)  # prints 12
print callback2(5)    # prints 17

这是我的代码片段:

def printParam(parameter):
    print "You selected %s" % parameter


# parameters = list of strings

menu_bar = QMenuBar()
menu = menu_bar.addMenu('Select Parameter')
for parameter in parameters:
    # This line will not work because the action does not pass in
    # any arguments to the function
    menu.addAction(parameter, printParam)

非常感谢任何建议

5 个回答

2

是的,这个叫做部分应用。标准库里有一个类可以用来部分应用一个函数,叫做 functools.partial。在你的例子中,你可以写 partial(f, x=7) 或者 partial(f, 7)(因为这是一个位置参数,你不需要跳过任何位置参数)。

6

functools.partial() 这个功能可以让你提前提供一些参数。这样一来,你就可以根据自己的需要创建自定义的回调函数。

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
4

你可以使用一个闭包,像这样:

def printParam(parameter):
    def callback():
        print "You selected %s" % parameter
    return callback

for parameter in parameters:
    menu.addAction(parameter, printParam(parameter))

撰写回答