【问题标题】:Python dynamic function namesPython 动态函数名
【发布时间】:2010-10-15 10:06:47
【问题描述】:

我正在寻找一种更好的方法来调用基于 Python 中的变量的函数,而不是使用下面的 if/else 语句。每个状态码都有对应的功能

if status == 'CONNECT':
    return connect(*args, **kwargs)
elif status == 'RAWFEED':
    return rawfeed(*args, **kwargs)
elif status == 'RAWCONFIG':
    return rawconfig(*args, **kwargs)
elif status == 'TESTFEED':
    return testfeed(*args, **kwargs)
...

我认为这需要某种工厂函数,但不确定语法

【问题讨论】:

    标签: python factory


    【解决方案1】:

    我猜你可能会发现 getattr 很有用

    import module
    getattr(module, status.lower())(*args, **kwargs)
    

    【讨论】:

    • 感谢这个例子,我没有意识到 getattr() 也适用于模块
    【解决方案2】:

    执行此操作的规范方法是使用字典来模拟 switchif/elif。您会在 SO 上找到类似问题的几个问题。

    将您的函数放入字典中,并以您的状态码作为键:

    funcs = {
        'CONNECT': connect,
        'RAWFEED': rawfeed,
        'RAWCONFIG' : rawconfig,
        'TESTFEED': testfeed
    }
    funcs[status](*args, **kwargs)
    

    【讨论】:

    • funcs['status'] 会引发 KeyError
    • 我认为这是一种安全的方法,当status 是一个意外的方法名称时会引发异常。
    • DRY 很少适用于这种情况。函数的初始列表可能具有类似字符串的名称;但这通常会分化为更复杂的关系。
    • @S.Lott:问题标题说明“动态函数名称”。这是静态映射。
    • 这不是函数分派的标准 Python 方式。 getattr 是这种情况下的规范方法
    【解决方案3】:

    假设这些函数属于某个模块:

    import module
    return getattr(module, status.lower()).__call__(*args, **kwargs)
    

    【讨论】:

      【解决方案4】:

      你可以以稍微不同的方式使用 getattr(我认为更优雅的方式)

      import math
      getattr(math, 'sin')(1)
      

      或者如果函数像下面这样导入

      from math import sin
      

      sin 现在在命名空间中,所以你可以调用它

      vars()['sin'](1)
      

      【讨论】:

        【解决方案5】:

        对 SilentGhost 的回答进行了一些改进:

        globals()[status.lower()](*args, **kwargs)
        

        如果要调用当前模块中定义的函数。

        虽然看起来很丑。我会使用字典的解决方案。

        【讨论】:

          【解决方案6】:

          【讨论】:

          • 链接失效,分数递减。很抱歉。
          【解决方案7】:

          我以前遇到过同样的问题。看看这个问题,我想它就是你要找的。​​p>

          Dictionary or If Statements

          希望对你有帮助

          伊夫

          【讨论】:

            【解决方案8】:

            与上一个相比有一些变化:

            funcs = {
            'CONNECT': connect,
            'RAWFEED': rawfeed,
            'RAWCONFIG' : rawconfig,
            'TESTFEED': testfeed
            }
            
            func = funcs.get('status')
            if func:
                func(*args, **kwargs)
            

            【讨论】:

            • 不,它没有。这和海科格拉赫一开始的错误是一样的。
            • 我用变量替换了'status',所以我想从技术上讲它没有。我对方法比语义更感兴趣
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-11
            • 1970-01-01
            • 1970-01-01
            • 2012-10-23
            • 2012-10-22
            相关资源
            最近更新 更多