正在查找“SupportsRound”的工作示例`

2024-06-08 00:55:31 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

测试通过了,即在对round的两个调用中,我都得到了一个类型为MyClass的对象。但是MyPy检查只有在调用round而没有参数时才会失败。你知道吗

版本号: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

Tags: self信息类型参数deftypemyclassassert
1条回答
网友
1楼 · 发布于 2024-06-08 00:55:31

我相信这里的问题与SupportsRound的使用关系不大,而与round函数的定义关系更大。round函数是在typeshed中定义的,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没有参数时,输出总是int。这与标准库中round函数的行为一致:https://docs.python.org/3/library/functions.html#round

不幸的是,我没有看到一种真正干净的方法来解决这个问题:我认为implementation of SupportsRound与这种行为并不一致。你知道吗

具体来说,SupportsRound可能应该这样定义:

@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旧版本。你知道吗

我建议你在打字问题跟踪器上写一个问题。我个人认为你已经发现了一个真正的不一致性/错误,但这里可能有一些细微差别,我错过了,所以我认为这将是一个很好的升级。你知道吗

相关问题 更多 >

    热门问题