【问题标题】:Return-if-value idioms (conditional returning)Return-if-value 习语(条件返回)
【发布时间】:2013-02-08 15:33:21
【问题描述】:

最近我发现自己在一些函数中使用了以下成语:

[...]
def validate(self):
    # Possibly do something "expensive" to calculate whether data is valid or not
    if data_is_valid:
        return ObjectOfSomeSort(validated_data)
    return False

ret = self.validate()
if ret:
    return ret
[...]

我觉得 ret = ...; if ret: return ret 语法有点笨拙和不符合 Python 标准,但我并不总是能够做类似的事情

if self.validate():
    return self.validate()

因为有时我的验证函数包含一些计算量相当大的逻辑。

那么,StackOverflow,有哪些 Python 习语可以解决这类问题;具体来说,我还能如何“有条件地返回”?

【问题讨论】:

  • 我必须同意,这完全是非 Python 的,因为我实际上不明白你要做什么......如果很难解释,那是个坏主意:P
  • 如果数据无效,我的“验证”函数会返回 False。如果数据有效,我想尽早退出调用函数(调用 self.validate() 的函数);如果不是,我想继续执行流程。
  • 嗯,这里的语义似乎有点错误:self.validate() 暗示您要确保 current(!) 对象,又名 self有效。
  • 是的,你是对的——这就是我的代码所做的——但是我可能有点过度疲劳,并且在表达自己方面做得很差。
  • 方法名明显错误。如果对象有效,我希望validate 返回True,否则返回False

标签: python idioms


【解决方案1】:

Python 中的惯用语是使用异常。

   class InvalidDataError(Exception):
       pass

   def get_valid_object():
       if not data_is_valid:
           raise InvalidDataError()
       return ObjectOfSomeSort(validated_data)

然后使用它:

 try:
     valid_object = get_valid_object()
 except InvalidDataError:
     ... handle error

【讨论】:

  • 例外是我完全忘记的事情;谢谢!
【解决方案2】:

你可以的

def ifloop(x):
    if x: yield x

for ret in ifloop(self.validate()):
     return ret

【讨论】:

  • 我想我会先使用 if 块 ;-)。但有趣的是,巧妙地使用了生成器函数。
  • 聪明的生成器+1;这些是我正在寻找的答案;)
  • 运行时是NameError
  • 仅在“未定义 y”的情况下;出于同样的原因,我最初发布的问题的代码的 sn-p 也会NameError。不过,这与答案的重点很相近。
【解决方案3】:

如果代码在您的if 之后不需要继续,我会写:

return self.validate() or None

【讨论】:

  • 我喜欢这个,即使非python程序可能会感到困惑。
  • 这将返回 self.validate() 或者如果 self.validate() 不为真则返回 None;我希望非 True 案例继续执行(即永远不会触发 return 语句)
【解决方案4】:

您可以使用NULL object pattern,确保添加以下方法,这样它的实例也将被视为 False——这将使其更容易测试:

def __nonzero__(self) :
    return False

这种Null 对象的用处在于,它们可以像几乎任何其他对象一样使用,因此在许多情况下,您不必在其余代码中检查它们,因为它可以假设它有一个有效的对象其他类型。

我在 Alex Martelli 的 Python Cookbook 第二版中第一次听说这种模式。这是食谱6.17

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-09
    • 2013-08-04
    • 1970-01-01
    • 2016-09-03
    • 1970-01-01
    • 2015-03-22
    • 2022-01-03
    • 2017-02-05
    相关资源
    最近更新 更多