【问题标题】:Inner function in python doesn't return at the right placepython中的内部函数没有在正确的位置返回
【发布时间】:2020-02-21 06:40:47
【问题描述】:

在我的内部函数的以下代码中,无论分数如何,返回的唯一值都是(0, None)。我可以看到for 循环在团队达到胜利或怜悯阈值时终止,但这并不作为整个函数的返回值。我不记得 return 语句是这样工作的,所以有人可以解释一下为什么会这样吗?

    def victory_check() -> Tuple[Optional[int], Optional[Team]]:
        scores_all_bad: bool = True
        for team in tea_lst:
            print(team.score)  # debug
            if team.score >= victory_threshold:
                return 1, team
            if team.score < mercy_rule:
                return -1, team
            if team.score > bad_ai_end:
                scores_all_bad = False
        if scores_all_bad:
            return -1, None
        return 0, None

Team 对象由以下内容构成。测试工具将 -12 到 14 之间的随机整数添加到每个团队的分数中,以假装玩一手牌。 Team.score 值正确反映在打印语句中。

class Team:
    players: List[Player]
    score: int = 0
    bid: int

    def __init__(self, players: List[Player]):
        self.players = players

【问题讨论】:

  • 您能否更清楚地说明您的输入和输出的外观?
  • " 我可以看到,当团队达到胜利或怜悯阈值时,for 循环终止" 是吗?还是在那之后巧合地终止了?因为return 确实从(最近的)封闭函数返回。而且由于 select 没有损坏,因此您在执行代码时可能缺少一些东西。而且由于您没有提供复制方式,因此很难分析问题。
  • 无论如何,使用一些合成值似乎可以按预期工作:假设 bad_ai_end = 0;victory_threshold = 9;怜悯规则 = -10 和得分为 10、5、-5 和 -100 的单个团队的序列我得到 1, team0, None-1, None-1, team 的结果,这与代码的假设一致去做。
  • 原来错误是在测试循环中,而不是我想的函数。

标签: python return control-flow


【解决方案1】:

不确定您的 team_list 是什么样的。假设它是一个字典列表,则此代码按预期工作。

team_lst = [{'score': 40}]
def victory_check():
    scores_all_bad: bool = True
    for team in team_lst:
        print(team.keys())
        print(team.get('score'))  # debug
        if team.get('score') >= 5:
            return 1, team
        if team.get('score') < 5:
            return -1, team
        if team.get('score') > 100:
            scores_all_bad = False
    if scores_all_bad:
        return -1, None
    return 0, None

【讨论】:

    【解决方案2】:

    根据documentation

    return 将当前函数调用与表达式列表(或 无)作为返回值。

    因此,一个函数执行(不返回)多个返回语句的唯一方法是当你有一个 try-except 块在 finally 块中运行一个参数时。像下面的东西。需要明确的是,(Python 内部执行了两次返回,但实际上只返回了一次)

    def nums(list_ofvals):
    
        score = True
        try:
            for v in list_ofvals:
                if v == 1:
                    return "one return", 1
    
                elif v == 3:
                    return "three return", 3
        except:
            pass
    
        finally:
            if score == True:
                return "true score"
            else:
                pass
    
    print(nums([1])) #function call
    

    【讨论】:

    • 虽然可以用finally 块中的另一个return 语句覆盖以前“执行”的return 语句,但这绝对是一种不好的风格,应该几乎总是可以避免的。在您的示例中,循环中放置得当的break 可以实现相同的效果并且更加清晰。
    • 我同意这一点。我的论点是,afaik 触发两个 return 语句的唯一方法是使用 try/except 块和 finally 显然会覆盖你所说的。所以这个用户发布的问题不能像他所说的那样工作。我的代码只是一个例子,说明什么是可能的,什么不是......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    相关资源
    最近更新 更多