测试字典键是否存在的条件始终为 False

2022-01-21 00:00:00 python dictionary conditional

问题描述

我创建了一个函数,它使用两个字典,curr_statsweekly_result.如果 weekly_result 中有任何键不在 curr_stats 中,则该函数应该只打印 invalid_msg,没有 curr_stats.

I made a function that consumes two dictionaries, curr_stats and weekly_result. If there are any keys in weekly_result that aren't in curr_stats, the function is supposed to just print invalid_msg, with no mutation of curr_stats.

但我的代码第 5 行的 if 语句似乎不起作用.它应该触发下一个 if 语句,因此 curr_stats 不会发生突变.

But the if statement on the 5th line of my code doesn't seem to be working. It's supposed to trigger the next if statement, so no mutation of curr_stats occurs.

def update_standings(curr_stats, weekly_result):
    invalid = 0
    point_counter(weekly_result)
    for team in weekly_result:
        if team in curr_stats == False:
            invalid = invalid + 1
    if invalid > 0:
        print(invalid_msg)
    else:
        for team in weekly_result:
            curr_stats[team] = curr_stats[team] + weekly_result[team]


解决方案

在 Python 中,所有比较都有相同的优先级,包括in.正在发生的事情是 比较链,一种旨在测试传递关系的特殊形式就像在数学课上一样:

In Python, all comparisons have the same precedence, including in. What's happening is comparison chaining, a special form intended to test transitive relationships like in math class:

if x_min < x < x_max:
    ...

作为 PawełKordowski 在他的评论中指出,上面的比较链大多相当于:

As Paweł Kordowski pointed out in his comment, the above comparison chain is mostly equivalent to:

if x_min < x and x < x_max:
    ...

(有一个区别:等效"代码可能会计算两次 x,而比较链仅计算一次 x.)

(There is one difference: The "equivalent" code might evaluate x twice, while the comparison chain evaluates x exactly once.)

在您的情况下,比较链是:

In your case, the comparison chain is:

if team in curr_stats == False:
    ...

...(大部分)等同于:

...which is (mostly) equivalent to:

if team in curr_stats and curr_stats == False:
    ...

仅当 curr_stats 包含 team 并且 curr_stats 为空时才适用……这绝不应该发生.

This is only true if curr_stats contains team and curr_stats is empty... which should never happen.

您的代码的问题是 == False --- 部分是因为它将比较变成了比较链,但主要是因为您从一开始就不需要它.当你想要一个布尔值的对立面时,Python 提供了 not 关键字.您的条件语句应为:

The problem with your code is the == False --- in part because it turned a comparison into a comparison chain, but mostly because you never needed it in the first place. Python provides the not keyword for when you want a Boolean's opposite. Your conditional statement should read:

if team not in curr_stats:
    invalid = invalid + 1

最后一个建议:通过去掉 invalid 计数器并在发现无效的 team 时立即返回,可以使这个函数变得更短.(一旦您发现 weekly_result 是无效输入,您可能就不会关心它是否甚至无效".)我还使用了 dict.items 简化最终的 for 循环:

One last suggestion: This function can be made even shorter by getting rid of the invalid counter and just returning as soon as an invalid team is found. (Once the you've discovered that weekly_result is invalid input, you probably don't care if it's "even more invalid".) I also used dict.items to simplify the final for loop:

def update_standings(curr_stats, weekly_result):
    point_counter(weekly_result)
    for team in weekly_result:
        if team not in curr_stats:
            print(invalid_msg)
            return
    for team, result in weekly_result.items():
        curr_stats[team] += result

相关文章