MyPy 中的相同类型如何不兼容?

Nei*_*l G 12 python mypy python-typing

使用以下示例:

from typing import Callable, Generic, Type, TypeVar

ThetaType = TypeVar('ThetaType', bound=int)
XType = TypeVar('XType', bound=int)


class IteratedFunction(Generic[ThetaType, XType]):

    def find_fixed_point(self,
                         theta: ThetaType,
                         x_init: XType) -> XType:
        return x_init


def combinator(
    iterated_function_cls: Type[
        IteratedFunction[ThetaType, XType]]) -> Callable[
            [IteratedFunction[ThetaType, XType]], XType]:
    old_find_fixed_point = iterated_function_cls.find_fixed_point

    def new_find_fixed_point(
            iterated_function: IteratedFunction[ThetaType, XType],
            theta: ThetaType,
            x_init: XType) -> XType:
        return old_find_fixed_point(iterated_function, theta, x_init)

    return new_find_fixed_point
Run Code Online (Sandbox Code Playgroud)

MyPy 说:

a.py:25: error: Incompatible return value type (got "XType", expected "XType")
a.py:25: error: Argument 1 has incompatible type "IteratedFunction[ThetaType, XType]"; expected "IteratedFunction[ThetaType, XType]"
a.py:25: error: Argument 2 has incompatible type "ThetaType"; expected "ThetaType"
a.py:25: error: Argument 3 has incompatible type "XType"; expected "XType"
a.py:27: error: Incompatible return value type (got "Callable[[IteratedFunction[ThetaType, XType], ThetaType, XType], XType]", expected "Callable[[IteratedFunction[ThetaType, XType]], XType]")
Run Code Online (Sandbox Code Playgroud)

JL *_*ret 1

我不确定我是否同意这个问题的前提。

\n\n

Here\xe2\x80\x99s 3.8文档字符串的一部分

\n\n
class TypeVar(_Final, _Immutable, _root=True):\n    """Type variable.\n    Usage::\n      T = TypeVar(\'T\')  # Can be anything\n      A = TypeVar(\'A\', str, bytes)  # Must be str or bytes\n\n    ....\n    def __init__(self, name, *constraints, bound=None,\n                 covariant=False, contravariant=False):\n    ....\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,如果你刚刚

\n\n
ThetaType = TypeVar(\'ThetaType\')\nXType = TypeVar(\'XType\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

您是否认为 ThetaType 的使用应该被视为 XType 的使用,即使设置了 2 个不同的类型变量?为什么添加bound可选参数会自动将它们折叠在一起?源代码不以任何方式强制存在绑定或名称旁边的任何参数。

\n\n

我不认为\xe2\x80\x99s打字/mypy\xe2\x80\x99s工作来推断你在类型声明中的意图,只是为了检查你的代码与你声明的类型意图。如果您希望它们相同,则仅声明 1 个 TypeVar。如果您确实有理由拥有 2,那么将它们视为相同可能会失去一些语义意义。

\n\n

I\xe2\x80\x99ll 添加到它比在子类上匹配时bound具有更大的灵活性。constraints让\xe2\x80\x99s 说你\xe2\x80\x99用户定义了int的4个子类。Int1(int)、Int2、Int3、Int4...现在您\xe2\x80\x99决定对代码进行分区,其中某些代码应该只接受Int1和Int2。Typevarint12 可以在某种程度上表达这一点,即使您的子类都匹配bound=int.

\n

  • @NeilG那么也许你应该修改你的问题,以便标题和你对显示这种意外行为的特定代码的评论表明为什么你期待不同的东西。现在,我在 TypeVar 构建块本身中没有看到任何内容表明为什么 2 个类型变量应该表现相同。如果您围绕 TypeVar 设置代码的方式应该导致等效,那么请解释这一点,但不要*仅将其固定在 TypeVar* 上。 (3认同)