【问题标题】:mypy: Why is "int" a subtype of "float"?mypy:为什么“int”是“float”的子类型?
【发布时间】:2021-11-28 23:00:18
【问题描述】:

为什么“mypy”将“int”视为“float”的子类型?子类型应支持其父类型的所有方法,但“float”具有“int”不支持的方法:

test.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.readthedocs.io/en/latest/duck_type_compatibility.html
  • @BlackFrog 不,它不能。
  • @BlackFrog An int 不能放入浮点数。 Python ints 不是机器 ints。 (无论如何,我不确定这与类型检查有什么关系,这并不真正关心类型的运行时表示。)
  • @StefanPochmann 是的,但如图所示,从类型系统 POV 来看,它不是
  • @StefanPochmann 感谢您发现这一点,我在 github 中寻找一些相关问题。但请注意,Guido 甚至在使用 .hex 方法引用类似问题时说(可能是一个错误?)。虽然,我认为在这种情况下,这意味着应该实现int.hex,实际上,int.is_integer 也可以实现。老实说,这对我来说是最好的解决方案。

标签: python mypy


【解决方案1】:

'为什么“mypy”将“int”视为“float”的子类型?'

因为到目前为止,实用性一直被认为要胜过纯度。这并不是说不能建议键入定义一个包含整数和浮点数但仅对算术运算有效的标量类型。

请注意 int / int 在 3.0 中进行了更改,因此 float(int / int) == float(int) / float(int),以使 int 和 float 算法对于相等的 int 和 float 值保持一致。

另请注意,类型检查通过并不意味着没有运行时错误:除以零和溢出仍然可能,以及许多其他错误。

【讨论】:

    【解决方案2】:

    正如@juanpa.arrivillaga所指出的,解释在https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html

    子类型应支持其父类型的所有方法,但“float”有方法,“int”不支持

    int 不是float 的子类型,因此它不必支持float 的方法。

    该机制很好,因为传递整数值不应导致错误,除非您真的像示例中那样需要它们。您明确尝试使用不存在的方法。通常情况下,我们只对数字进行算术运算,因此很少存在问题,您可以随时通过添加.0 来避免它。

    在大多数语言中,假设intfloat 的特例是一种常见的行为,例如考虑C++ 中的intfloat 的隐式转换。

    【讨论】:

    • 老实说,说“你总是可以通过使用正确的类型来避免它”对我来说并不是一个令人信服的论点,因为类型检查器是错误的。
    • 静态类型的整个point 正是为了避免 使用未为该类型定义的方法。答案的第一部分很好;继续解释为什么没有缺点只是在伤害每个人。
    猜你喜欢
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多