python - 寻找 `SupportsRound` 的工作示例

标签 python mypy

网上没有很多关于使类型注释与 __round__ 一起工作的详细信息。我已经实现了这个但是当我运行 mypy 时我仍然在第 16 行(调用 round 没有 ndigits 参数)出现错误:

error: Incompatible types in assignment (expression has type "int", variable has type "MyClass")

测试通过,即在对 round 的两次调用中,我都返回了一个类型为 MyClass 的对象。但是只有当我调用 round 时没有参数,MyPy 检查才会失败。

版本号:Python 3.6.5,mypy 0.641。

from typing import Any, SupportsRound, overload

class MyClass(SupportsRound['MyClass']):

    def __round__(self: 'MyClass', ndigits: int = 0) -> 'MyClass':
        return self


def test_tmp() -> None:
    x = MyClass()
    result: MyClass

    result = round(x, 0)
    assert type(result) == MyClass
    result = round(x)
    assert type(result) == MyClass

最佳答案

我相信这里的问题与您对 SupportsRou​​nd 的使用关系不大,而与 round 函数的定义有关。 round 函数在 typeshed 中定义,这是标准库的类型提示存储库,具有 the following signature :

@overload
def round(number: float) -> int: ...
@overload
def round(number: float, ndigits: None) -> int: ...
@overload
def round(number: float, ndigits: int) -> float: ...
@overload
def round(number: SupportsRound[_T]) -> int: ...
@overload
def round(number: SupportsRound[_T], ndigits: None) -> int: ...  # type: ignore
@overload
def round(number: SupportsRound[_T], ndigits: int) -> _T: ...

请注意,当仅提供一个参数或 ndigits 为 None 时,输出始终为 int。这与标准库中记录的 round 函数行为一致:https://docs.python.org/3/library/functions.html#round

不幸的是,我没有看到一个真正干净的方法来解决这个问题:我不认为 implementation of SupportsRound确实符合这种行为。

具体来说,SupportsRou​​nd 可能应该定义如下:

@runtime
class SupportsRound(Protocol[_T_co]):
    @abstractmethod
    @overload
    def __round__(self, ndigits: None = None) -> int: ...

    @abstractmethod
    @overload
    def __round__(self, ndigits: int) -> _T_co: ...

基本上,强制用户处理这两种情况。

但实际上更改定义可能会很复杂:实际上并没有一种干净的方法来更新与旧版本的打字模块捆绑在一起的任何旧版本的 Python。

我建议在 typeshed issue tracker 上提交关于此的问题。我个人认为您在这里发现了一个真正的不一致/错误,但这里可能存在一些我遗漏的细微差别,所以我认为最好将其升级。

关于python - 寻找 `SupportsRound` 的工作示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53481887/

相关文章:

python - OpenCV匹配模板-阈值永远不等于1

python - 在使用 scikit-learn 在 Pipeline 中拟合 ML 模型后,如何将准确度与 Score() 函数中的另一个性能指标交换?

python - Callable 是无效的基类?

python - 如何注释数据类中的字段类型与其__init__的类型不同?

Python 版本依赖类型注解

python - 如何使用可选导入键入提示?

android - 从 kivy/python 程序创建适用于 Android 的 APK

python - 维护 PIP 存储库

python Pandas : Conditional rolling count

python 3.6 : Signature of {method} incompatible with super type {Class}