mypy 为什么抱怨可选列表中的包含检查不总是布尔值?

huangapple go评论85阅读模式
英文:

Why does mypy complain that inclusion checks in optional lists aren't always booleans?

问题

我有以下的代码片段(展开以便更清晰地解释),我预期它们始终具有布尔变量类型。然而,mypy 表示第二和第三个类型并不总是 bool,而是 listNonebool 的联合。

如果我将第二行更改为 a is not None(以及第三行),则指定的类型变得正确。既然这些表达式始终是条件的,为什么需要 is not None 呢?

这是显示错误的 playground 链接: https://mypy-play.net/?mypy=latest&python=3.11&flags=verbose&gist=14167cfb7554c2c94c3bd65d2710d017

英文:

I have the following piece of code (expanded out for a clearer explanation) that I expected to always have boolean variable types. However, mypy indicates that the second and third types are not always bool but instead a union of list, None, and bool.

a: list[str] | None = None
b: list[str] | None = None

def f(test: str) -> bool:
    flag: bool = not a and not b
    flag2: bool = a and test in a
    flag3: bool = b and test not in b
    return flag or flag2 or flag3

If I change the second line to a is not None (along with the third), the indicated typing becomes correct. Shouldn't the types resolve to boolean since the expressions are always conditionals? Why is the is not None necessary?

Here is the playground link showing the error: https://mypy-play.net/?mypy=latest&python=3.11&flags=verbose&gist=14167cfb7554c2c94c3bd65d2710d017

答案1

得分: 4

在Python中,**and**不是一个布尔操作,尽管它可以(而且通常也会)被用作布尔操作。a and b会返回a,如果a为假,否则返回b。要了解为什么这个定义可以作为布尔操作:

False and False == False  # (a为假,结果为a)
False and True  == False  # (a为假,结果为a)
True and False  == False  # (a不为假,结果为b)
True and True   == True   # (a不为假,结果为b)

然而,对于非布尔操作数:

"" and 0        == ""  # (a为假,结果为a)
"" and 42       == ""  # (a为假,结果为a)
"answer" and 0  == 0   # (a不为假,结果为b)
"answer" and 42 == 42  # (a不为假,结果为b)

当强制转换为布尔值,例如通过条件语句,它仍然像布尔结果一样运行,但实际上它不是。因此,and操作的结果类型是其参数的类型的并集。由于alist[str] | None,而test in abool,所以a and test in alist[str] | None | bool。具体来说,如果a[],仍然属于list[str],那么flag2最终会成为一个非布尔的[]

英文:

and in Python is not a Boolean operation, though it can be (and often is) used as one. a and b will return the a if it is falsy, or b otherwise. To see why this definition can function as a Boolean operation:

False and False == False  # (a is falsy, result is a)
False and True  == False  # (a is falsy, result is a)
True and False  == False  # (a is not falsy, result is b)
True and True   == True   # (a is not falsy, result is b)

However, with non-Boolean operands:

"" and 0        == ""  # (a is falsy, result is a)
"" and 42       == ""  # (a is falsy, result is a)
"answer" and 0  == 0   # (a is not falsy, result is b)
"answer" and 42 == 42  # (a is not falsy, result is b)

When coerced to a Boolean, e.g. by a conditional, it still functions as if the result was Boolean, but it is not. Thus, the type of the result of an and operation is a union of the types of its arguments. Since a is list[str] | None and test in a is a bool, a and test in a is list[str] | None | bool. Specifically, if a is [], which still falls under list[str], then flag2 would end up as a non-Boolean [].

答案2

得分: 2

不同于一些其他编程语言,在Python中,and 表达式不一定返回一个布尔值。

相反,它返回第一个值,如果它为假值(falsey),否则返回第二个值。

a and test in a

如果 a 为假值(在这种情况下可能是一个空列表),and 表达式将返回该值。

英文:

Unlike some other languages, in Python an and expression does not necessarily return a bool value.

Instead, it returns the first value if it is falsey, otherwise it returns the second value.

a and test in a

if a is falsey (in this case perhaps it is an empty list) the and will return that value.

huangapple
  • 本文由 发表于 2023年7月10日 11:52:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76650594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定