【问题标题】:Pythonic way for a conditional return in a function函数中条件返回的 Pythonic 方式
【发布时间】:2020-06-22 13:56:05
【问题描述】:

我有几个函数返回一个数字或None。我希望我的包装函数返回不是None 的第一个结果。除了以下还有其他方法吗?

def func1():
    return None
def func2():
    return 3
def func3():
    return None

def wrapper():
    result = func1()
    if result is not None:
        return result
    result = func2()
    if result is not None:
        return result
    result = func3()
    if result is not None:
        return result

我知道return func1() or alternative;它返回func1() 的结果,除非它是None,然后返回alternative。在最佳情况下,我会执行类似(伪代码)的操作:

return func1() or continue
return func2() or continue
return func3() or continue

【问题讨论】:

  • return func1() or func2() or func3() 呢?
  • 嗯,我已经更喜欢那个了!如果有五十个函数呢?
  • @jorijnsmit:在这种情况下,您将有一个真正的循环遍历函数列表,只有一个中断。

标签: python return


【解决方案1】:

您需要一个循环来返回它找到的第一个非None 值。

def wrapper():
    for f in [func1, func2, func3]:
        result = f()
        if result is not None:
            return result

如果每个函数都返回Nonewrapper 也会在没有显式return 的情况下到达主体的末尾。

在 Python 3.8 或更高版本中略有缩短,

def wrapper():
    for f in [func1, func2, func3]:
        if (result := f()) is not None:
            return result

你也可以使用any函数:

def wrapper():
    if any((result := f()) is not None for f in [func1, func2, func3]):
        return result

(我更喜欢显式循环;YMMV。)

【讨论】:

    【解决方案2】:

    如果只有三个函数,并且你不关心区分 None 和其他 false 值,你可以使用

    return func1() or func2() or func3()
    

    如果有很多函数,或者如果您想对返回值进行更多区分,那么您可以将它们全部放在一个列表中并使用

    return next(x for x in (f() for f in funcs) if x is not None)
    

    如果你想处理所有返回 None 的函数,你可以为 next 添加一个默认值,例如

    return next((x for x in (f() for f in funcs) if x is not None), None)
    

    【讨论】:

      【解决方案3】:

      你可以结合map、filter和next:

      def func1():
          print("executed func1()")
          return None
      def func2():
          print("executed func2()")
          return 3
      def func3():
          print("executed func3()")
          return None
      
      functions = (func1,func2,func3)
      call      = lambda f:f()
      result    = next(filter(None,map(call,functions)),None)
      
      print("result:",result)
      

      输出:

      executed func1()
      executed func2()
      result 3
      

      func 3 未执行

      如果您的函数有参数,您仍然可以通过使用 lambda 构建函数列表来使用此方法:

      def func1(p1):
          print(f"executed func1({p1})")
          return None
      def func2(p2a,p2b):
          print(f"executed func2{(p2a,p2b)}")
          return 3
      def func3(p3):
          print(f"executed func3({p3})")
          return None
      
      functions = [
                     lambda: func1(10),
                     lambda: func2("X",99),
                     lambda: func3(3.5)
                  ]
      call      = lambda f:f()
      result    = next(filter(None,map(call,functions)),None)
      
      print(result)
      

      输出:

      executed func1(10)
      executed func2('X', 99)
      3
      

      【讨论】:

      • 感谢lambda 的构造,能够传递不同的参数真的很有用!
      【解决方案4】:

      你可以这样做:

      def wrapper():
          functions = [func1, func2, func3]
          return next(filter(lambda result: result is not None,
                             f() for f in functions),
                      None)
      

      如果所有函数都返回None,则返回None

      【讨论】:

        猜你喜欢
        • 2014-09-06
        • 1970-01-01
        • 2019-06-28
        • 2011-12-23
        • 2014-03-31
        • 1970-01-01
        • 1970-01-01
        • 2017-04-19
        • 2010-09-08
        相关资源
        最近更新 更多