Python函数指针


75

我将函数名称存储在这样的变量中:

myvar = 'mypackage.mymodule.myfunction'

现在我要这样调用myfunction

myvar(parameter1, parameter2)

最简单的方法是什么?


4
为什么不存储函数本身?myvar = mypackage.mymodule.myfunction更干净。
ironfroggy

1
在下面的注释中:«它必须是字符串,因为在定义的地方,应用程序不知道所需的功能,因为它是通用应用程序。» – schneck
badp 2010年

Answers:


112
funcdict = {
  'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
    ....
}

funcdict[myvar](parameter1, parameter2)

1
我想知道如果函数要被调用很多次(在循环,递归等中)会给性能带来什么影响?
zanlok 2011年

5
该引用已解决,因此,仅在dict中进行查找需要花费调用调用本地函数之外的任何时间。甚至可以通过只查找一次来缓解这种情况。
伊格纳西奥·巴斯克斯

这是什么“ mypackage.mymodule.myfunction”?在哪里可以阅读更多内容?
Orvar Korvar '17

@OrvarKorvar:替换为您选择的名称和参考。
伊格纳西奥·巴斯克斯

啊,现在我明白了。fundict是一本字典。
Orvar Korvar '17

41

能够只存储函数本身会更好,因为它们是python中的一流对象。

import mypackage

myfunc = mypackage.mymodule.myfunction
myfunc(parameter1, parameter2)

但是,如果必须动态导入软件包,则可以通过以下方法实现:

mypackage = __import__('mypackage')
mymodule = getattr(mypackage, 'mymodule')
myfunction = getattr(mymodule, 'myfunction')

myfunction(parameter1, parameter2)

但是请记住,所有这些工作都适用于您当前所在的任何范围。如果您不以某种方式坚持使用它们,那么如果您离开本地范围,就不能指望它们会继续存在。


15
def f(a,b):
    return a+b

xx = 'f'
print eval('%s(%s,%s)'%(xx,2,3))

输出值

 5

我会投票反对。它可能不是最好的解决方案,但我确实认为这是一个有用的答案,因为它显示了完整的可行示例。
布莱恩·奥克利

5
@zanlok是的!:-)那时我还不知道。
Pratik Deoghare,2011年

@PratikDeoghare是python的iam初学者,您可以解释一下(xx ='f')在做什么,谢谢。
RaHuL

9

最简单的

eval(myvar)(parameter1, parameter2)

您没有函数“指针”。您有一个函数“名称”。

尽管这很好用,但是您将有很多人告诉您这是“不安全的”或“安全风险”。


1
“不安全”:如果myvar来自用户输入,则是:)
Federico A. Ramponi 2010年

1
@schneck,那么为什么它可能必须是字符串?
Mike Graham 2010年

2
@schneck:如果eval('string')不能产生正确的函数,则您的问题不完整。您已经省略了一些关键的内容。您可以尝试发布有效的内容以及不起作用的详细错误消息。
S.Lott

2
@Derrick Turn,@ Truptych:只有当字符串来自恶意社交病患者时,它们才是正确的。互联网上未经身份验证的人的用户输入可能涉及恶意社交行为。通常,大多数其他内容都不涉及恶意社交行为,从而将安全风险降低到与删除该应用程序的所有源代码完全相同的风险。
S.Lott

6
@schneck,我不明白您的意思是“因为它是通用应用程序”在这里的意思。如果已将其定义为字符串文字,则您已经足够了解它,而无需这样做。
Mike Graham 2010年

6

为什么不存储函数本身?myvar = mypackage.mymodule.myfunction更干净。


4
modname, funcname = myvar.rsplit('.', 1)
getattr(sys.modules[modname], funcname)(parameter1, parameter2)

2

eval(compile(myvar,'<str>','eval'))(myargs)

compile(...,'eval')仅允许一个语句,因此调用后不能有任意命令,否则将出现SyntaxError。然后,进行一点点验证就可以至少将表达式约束到您能控制的范围,例如测试“ mypackage”是否启动。


2

在创建用于处理身份验证的库时遇到了类似的问题。我希望使用我的库的应用程序所有者能够在该库中注册一个回调,以检查针对经过身份验证的人员所在的LDAP组的授权。配置作为传入的config.py文件传入并包含一个dict所有的配置参数。

我得到这个工作:

>>> class MyClass(object):
...     def target_func(self):
...         print "made it!"
...    
...     def __init__(self,config):
...         self.config = config
...         self.config['funcname'] = getattr(self,self.config['funcname'])
...         self.config['funcname']()
... 
>>> instance = MyClass({'funcname':'target_func'})
made it!

有pythonic-er的方法吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.