为什么“mypy”将“int”视为“float”的子类型?子类型应支持其父类型的所有方法,但“float”具有“int”不支持的方法:
测试.py:
def f(x : float) -> bool:
return x.is_integer()
print(f(123.0))
print(f(123))
静态类型检查器接受为“float”参数传递“int”参数:
(3.8.1) myhost% mypy test.py
Success: no issues found in 1 source file
但这并不能保证运行时没有错误:
(3.8.1) myhost% python test.py
True
Traceback (most recent call last):
File "test.py", line 5, in <module>
print(f(123))
File "test.py", line 2, in f
return x.is_integer()
AttributeError: 'int' object has no attribute 'is_integer'
因为“float”有额外的方法,而“int”没有。
'为什么“mypy”将“int”视为“float”的子类型?'
因为到目前为止,实用性在这里被认为胜过纯粹性。 这并不是说不能建议类型定义一种标量类型,该类型包含整数和浮点数,但仅对算术运算有效。
请注意,int / int 在 3.0 中发生了更改,因此 float(int / int) == float(int) / float(int),以使 int 和 float 算术对于相等的 int 和 float 值一致。
另请注意,类型检查通过并不意味着没有运行时错误:被零除和溢出以及许多其他错误仍然是可能的。
更新:从Python 3.8开始,整数现在有一个.as_integer_ratio方法,从3.12开始,整数将获得一个.is_integer方法,只留下专门的.hex和.from_hex作为float-only。
正如@juanpa.arrivillaga所指出的,解释位于https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html。
子类型应支持其父类型的所有方法,但“float”具有“int”不支持的方法
int
是不是 float
的子类型,因此它不必支持float
的方法。
该机制很好,因为传递整数值不会导致错误,除非您确实想要像示例中那样。您明确尝试使用不存在的方法。在常见情况下,我们只对数字进行算术运算,因此很少存在问题,您可以按照您所写的添加
.0
来避免它。
在大多数语言中,假设
int
是 float
的特殊情况是一种常见行为,例如考虑 C++ int
到 float
的隐式转换。