【问题标题】:Is it better to use 'elif' or consecutive 'if' statements alongside return statements?在 return 语句旁边使用 'elif' 或连续的 'if' 语句会更好吗?
【发布时间】:2021-11-18 10:22:51
【问题描述】:

这个问题专门针对编码约定。我知道在这种情况下使用 if 或 elif 会产生相同的结果。只是想知道构造这个函数的“正确”方式是什么:

如果是连续的:

def can_take(self, selectedCourse):
    if selectedCourse.hasPassed():
        return False
    if selectedCourse.getPrereqs() != 'none':
        for prereq in selectedCourse.getPrereqs():
            if not self.courses[prereq].hasPassed():
                return False

    return True

使用 elif:

def can_take(self, selectedCourse):
    if selectedCourse.hasPassed():
        return False
    elif selectedCourse.getPrereqs() != 'none':
        for prereq in selectedCourse.getPrereqs():
            if not self.courses[prereq].hasPassed():
                return False

    return True

【问题讨论】:

  • 你想触发两个 if 语句下的两个代码吗?那么只有当你不想触发两个 if 语句时才可以使用,然后使用 elif
  • @GhostOps 你不能那样做;如果第一个为 True,则函数立即返回。作为个人喜好,我会使用两个 if 语句。
  • 顺便说一句,如果 getPrereqs() 返回一个空列表而不是 none 如果没有先决条件,则此代码可以更简单。
  • @chepner 我希望是这样。不幸的是,我只能修改这个项目中的一些模块。所以我必须使用 'none' 而不是 [] 大声笑

标签: python function for-loop object if-statement


【解决方案1】:

如果我必须在两者之间进行选择,我可能会使用两个 if 语句,但这只是个人喜好问题。

如果我有 第三个​​ 选择,我不会有 any return 带有布尔文字的语句。我会写一个使用andorreturn 语句。

return (not selected.hasPassed()
        and (selected.getPrereqs() == 'none'
             or all(x.hasPassed() 
                    for x in selected.getPrereqs()))

这与你用英语描述的方式很接近:如果你没有通过它,你可以参加该课程,并且如果课程没有任何先决条件或如果您已通过所有先决条件。

正如 John Kugelman 指出的那样,如果 getPrereqs 返回一个空列表而不是 'none',您可以进一步将其减少为

return (not selected.hasPassed()
        or all(x.hasPassed() 
               for x in selected.getPrereqs())

【讨论】:

  • 非常感谢您。单一的 return 语句是如此优雅。我不知道 all() 函数,将来肯定会使用它。
【解决方案2】:

我喜欢early return 模式:

首先排除无效的情况,简单地退出或适当地引发异常,在其中放置一个空行,然后添加方法的“真实”主体。我觉得它更容易阅读。

提早返回可以降低嵌套级别,这是减少认知负担的好方法。我会更进一步,将第二个if 语句翻转过来,这样它就太早返回了:

def can_take(self, selectedCourse):
    if selectedCourse.hasPassed():
        return False

    if selectedCourse.getPrereqs() == 'none':
        return True

    for prereq in selectedCourse.getPrereqs():
        if not self.courses[prereq].hasPassed():
            return False

    return True

也就是说,我会做一些其他改进:

  • 避免使用stringly typed 变量。将'none' 切换为None

  • 但是,当一个方法返回一个列表时,当没有结果时不要返回None。返回一个空列表。然后调用者可以盲目地遍历列表而不检查它是None 还是空的。

def can_take(self, selectedCourse):
    if selectedCourse.hasPassed():
        return False

    for prereq in selectedCourse.getPrereqs():
        if not self.courses[prereq].hasPassed():
            return False

    return True

如果您对generator expressions 感到满意,您甚至可以将循环转换为all(...) 调用,从而无需最后的return True

def can_take(self, selectedCourse):
    if selectedCourse.hasPassed():
        return False

    return all(self.courses[prereq].hasPassed()
        for prereq in selectedCourse.getPrereqs())

我喜欢这样,因为它更直接地表达了以下问题:“学生是否通过了所有的先决条件?”

【讨论】:

  • 谢谢你。我真的很喜欢这种结构。我最初考虑这样做,但是如果 for 循环永远不会返回 False,我仍然需要在函数末尾返回 True。所以最后,我只剩下一行额外的代码。
  • 另外,如上所述。我只能修改这个项目中的一些模块。我很想不使用“无”,但不幸的是我必须完成我的任务。
【解决方案3】:

我想我更喜欢第一个版本。为什么?当你有一个 if...elif...elif... 事物在每个分支中都有返回时,有两个“竞争”控制结构:if 语句和返回。显然,回报会“赢”,所以我们不妨删除 elif 的东西。要么,要么只有一个 return 语句,它返回一个由前面的 if...elif...elif...else 结构计算的值。

【讨论】:

  • 感谢您的回答。这也是我的想法。只是不确定使用“elif”是为了便于阅读还是出于其他原因。
  • 另一种看待它的方式是,两者只是等价的,因为if/elif 之后的代码仅包含另一个return。事实上,这两种情况都已经删除了隐含的else,它会返回True,所以从elif 中“剥离”else 也是有意义的。
【解决方案4】:

我们使用 elif,但请理解这取决于您的问题陈述。

注意:请不要用它创建一个大阶梯,因为这样会变得难以维护和调试代码。

【讨论】:

    猜你喜欢
    • 2017-02-05
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多