以下代码抛出mypy错误:
from typing import Dict, Any
def asd(x: Dict[str, Any]) -> bool:
return x['a'] == 1
asd({"x": 2})
IMO 什么作为命令通过并不重要。
x['a'] == 1
应始终为布尔值。但是 mypy 抱怨:
test.py:4: error: Returning Any from function declared to return "bool" [no-any-return]
除了用
# type: ignore[no-any-return]
填充我们的代码库之外,还有什么解决方法吗?
我的setup.cfg供参考:
namespace_packages = True
explicit_package_bases = True
check_untyped_defs = True
warn_return_any = True
warn_unused_ignores = True
show_error_codes = True
__eq__
方法,Python丰富的比较方法之一,并不always返回True
或False
,它也可以返回NotImplemented
(或其他值)。
这用于,例如,在第一种类型无法与第二种类型进行比较的情况下,因此
a.__eq__(b)
返回 NotImplemented
。在这种情况下,它会尝试 b.__eq__(a)
作为回退 (a)。如果那个 also 返回 NotImplemented
,那么我相信它会回到基本的 object
类型来找出相等性。
您可以看到
mypy
在其源代码中为此定义类型的方式,特别是mypy/mypy/typeshed/stdlib/_operator.pyi
:
def eq(__a: object, __b: object) -> Any: ...
这就是为什么你会收到那条特定的信息。
作为快速修复,您可以更改函数以返回
bool(x['x'] == 1)
。这 正是 Python 本身在评估布尔上下文中的返回值时所做的,因此应该可以接受mypy
(b).
(a)比那复杂little,还涉及两个项目的层次类型关系,但底线仍然存在:丰富的比较运算符并不总是返回
bool
。
(b) 数据模型的 Python 文档(我的重点)中对此进行了介绍:
丰富的比较方法可能会返回单例
如果它没有为给定的参数对实现操作。按照惯例,返回NotImplemented
和False
以进行成功比较。但是,这些方法可以返回 any 值,因此如果在布尔上下文中使用比较运算符(例如,在True
语句的条件中),Python 将调用if
值以确定是否结果是真还是假。bool()
有趣的是,虽然这不会改变这个答案的有效性,但之后的部分指出:
默认情况下,
通过使用object
实现__eq__()
,在错误比较的情况下返回is
:NotImplemented
.True if x is y else NotImplemented
但我不相信这是准确的。在实际代码中,
==
和!=
似乎都会导致True
或False
,具体取决于对象身份,并且永远不会返回NotImplemented
或引发异常(异常仅发生在排序比较时像<
或>=
):
/* If neither object implements it, provide a sensible default
for == and !=, but raise an exception for ordering. */
switch (op) {
case Py_EQ:
res = (v == w) ? Py_True : Py_False;
break;
case Py_NE:
res = (v != w) ? Py_True : Py_False;
break;
default:
_PyErr_Format(tstate, PyExc_TypeError, ...
正如评论中指出的那样,身份检查是在不同级别对基础对象进行的,例如,type objects。所以 我会对文档的那部分持保留态度 :-)