在Python中挂起函数调用以便稍后传递(函数范式)

0 投票
3 回答
514 浏览
提问于 2025-04-16 03:49

我正在写一个Python命令行程序,这个程序有一些相互依赖的选项,我希望用户可以随意输入这些选项的顺序。

现在我使用getopts库来解析命令行选项,但这个库是按顺序解析的。我想了一个办法,使用布尔标志来推迟处理某些命令行参数,直到处理它们依赖的那个参数。不过,我有个想法,使用一个优先队列来存储函数调用,这样在所有命令行选项解析完后再执行。

我知道Python可以把函数存储在变量名下,但这样似乎会立即调用这个函数。

举个例子:

help = obj.PrintHelp()
heapq.heappush(commandQ, (0, help))

这段代码会立即打印帮助信息。我该怎么做才能让我的代码在给PrintHelp一个名字时,不立即调用它呢?

编辑:哦,我刚意识到我把东西放进了一个叫help的队列,这是我的错误。

谢谢你提醒我去掉PrintHelp后面的()。

如果我现在想调用一个需要除了self以外更多参数的函数呢?

myFun = obj.parseFile(path)
heapq.heappush(commandQ, (1, myFun))

我是不是只需要把元组做大一点,传入命令行参数就行了?

3 个回答

0

如果你想在Python中保存一个完整的函数调用,有两种方法可以做到:

# option 1: hold the parameters separately
# I've also skipped saving the function in a 'help' variable'
heapq.heappush(commandQ, (0, obj.PrintHelp, param1, param2))

# later:
command = commandQ[0]
heapq.heappop(commandQ)
command[1](*command[2:]) # call the function (second item) with args (remainder of items)

另外,你也可以用一个助手来通过lambda把参数打包起来:

# option 2: build a no-argument anonymous function that knows what arguments
#           to give the real one
# module scope
def makeCall(func, *args):
    return lambda: func(*args)

# now you can:
help = makeCall(obj.PrintHelp, param1, param2)
heapq.heappush(commandQ, (0, help))

如果你需要关键字参数,告诉我,我会帮你处理这些。

1

与其使用getopts,我建议你使用optparse(如果你用的是较新的Python版本,可以用argparse):这样你很可能会得到你需要的所有功能,因为这些功能已经实现好了。

不过在你的示例代码中,你实际上是在调用这个函数,而你应该只是获取它的名字:

help = obj.PrintHelp 
heapq.heappush(help, (0, help)) 
2

如果你这样使用 heappush

myFun = obj.parseFile
heapq.heappush(commandQ, (1, myFun, path))

那么之后要调用这个函数,你可以这样做:

while commandQ:
    x=heapq.heappop(commandQ)
    func=x[1]
    args=x[2:]
    func(*args)

使用

help = obj.PrintHelp

时不要加括号。这样做是为了让 help 指向这个函数。之后,你可以用 help() 来调用这个函数。

另外,如果我理解你的情况没错,你其实可以直接使用标准库里的 optparse 模块,或者如果你用的是 Python2.7 或更高版本,可以用 argparse 模块,这样可以处理命令行选项,无论顺序如何。

顺便说一下,help 是 Python 内置的一个函数。如果你把一个变量命名为 help,就会覆盖掉这个内置函数,这样访问内置函数会变得困难(虽然不是不可能)。一般来说,最好不要覆盖内置函数的名字。

撰写回答