【问题标题】:Python function pointerPython函数指针
【发布时间】:2011-01-17 23:59:39
【问题描述】:

我有一个函数名存储在这样的变量中:

myvar = 'mypackage.mymodule.myfunction'

我现在想这样调用 myfunction

myvar(parameter1, parameter2)

实现这一目标的最简单方法是什么?

【问题讨论】:

  • 为什么不存储函数本身呢? myvar = mypackage.mymodule.myfunction 干净多了。
  • 来自下面的评论:«它必须是一个字符串,因为在定义它的地方,应用程序不知道所需的功能,因为它是一个通用应用程序。» – schneck

标签: python function-pointers


【解决方案1】:
funcdict = {
  'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
    ....
}

funcdict[myvar](parameter1, parameter2)

【讨论】:

  • 我想知道如果函数要被多次调用(在循环、递归等中),性能会受到什么影响?
  • 引用已经被解析,所以除了调用本地函数之外,只有字典中的查找需要任何时间。甚至可以通过仅查找一次来缓解这种情况。
  • 这是什么“mypackage.mymodule.myfunction”?我可以在哪里阅读更多相关信息?
  • @OrvarKorvar:替换为您选择的名称和参考。
  • 啊,现在我明白了。 fundict 是字典。
【解决方案2】:

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

import mypackage

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

但是,如果您必须动态导入包,那么您可以通过以下方式实现:

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

myfunction(parameter1, parameter2)

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

【讨论】:

    【解决方案3】:
    def f(a,b):
        return a+b
    
    xx = 'f'
    print eval('%s(%s,%s)'%(xx,2,3))
    

    输出

     5
    

    【讨论】:

    • 我会投赞成票来抵消反对票。这可能不是最好的解决方案,我认为这是一个有用的答案,因为它显示了一个完整的、有效的示例。
    • @zanlok 是的! :-) 那时我不知道。
    • @PratikDeoghare iam python 初学者你能解释一下 (xx = 'f') 在做什么吗谢谢。
    【解决方案4】:

    最简单

    eval(myvar)(parameter1, parameter2)
    

    您没有函数“指针”。你有一个函数“name”。

    虽然这很有效,但会有很多人告诉您这是“不安全”或“安全风险”。

    【讨论】:

    • "insecure": 如果 myvar 来自用户输入,是的 :)
    • @schneck,那为什么它可能必须是一个字符串?
    • @schneck:如果 eval('the string') 没有产生正确的函数,那么你的问题是不完整的。你遗漏了一些重要的东西。您可以尝试发布确实 有效的内容以及无效的详细错误消息。
    • @Derrick Turn,@Truptych:只有当字符串来自恶意反社会者时,他们才是正确的。来自互联网上未经身份验证的人的用户输入很可能涉及恶意反社会人士。大多数其他事情通常不涉及恶意反社会者,从而将安全风险降低到与删除应用程序所有源代码的风险完全相同。
    • @schneck,我不明白你所说的“因为它是一个通用的应用程序”在这里可能是什么意思。如果您已将其定义为字符串文字,则您已经对此了解得足够多,因此无需这样做。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:
      modname, funcname = myvar.rsplit('.', 1)
      getattr(sys.modules[modname], funcname)(parameter1, parameter2)
      

      【讨论】:

        【解决方案7】:

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

        compile(...,'eval') 只允许单个语句,因此调用后不能有任意命令,否则会出现 SyntaxError。然后一点点验证至少可以将表达式限制在您的能力范围内,例如开始测试“mypackage”。

        【讨论】:

          【解决方案8】:

          我在创建一个库来处理身份验证时遇到了类似的问题。我希望使用我的库的应用程序所有者能够向库注册回调,以检查经过身份验证的人员所在的 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的方法来做到这一点?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多