¿Cómo pueden los tipos idénticos ser incompatibles en MyPy?

7

Con el siguiente ejemplo:

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

MyPy dice:

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]")
Neil G
fuente
Parece que mypy interpreta new_find_fixed_pointcomo una función genérica con su propia instanciación separada de ThetaTypey XType.
user2357112 es compatible con Monica el
@ user2357112supportsMonica ¿Alguna idea de cómo podría solucionarlo?
Neil G
1
Echa un vistazo a github.com/python/mypy/issues/708 , parece un problema conocido que no es una prioridad. Confirme si está relacionado, por favor
Harsha Goli
1
@HarshaGoli: Eso parece similar a primera vista, pero parece ser un problema completamente diferente como resultado de cómo se manejan los métodos.
user2357112 es compatible con Monica el
1
@NeilG: Yo personalmente lo consideraría un error o una deficiencia en mypy.
user2357112 es compatible con Monica el

Respuestas:

0

No estoy seguro de estar de acuerdo con la premisa de esta pregunta.

Aquí hay parte de la cadena de documentación de 3.8

class TypeVar(_Final, _Immutable, _root=True):
    """Type variable.
    Usage::
      T = TypeVar('T')  # Can be anything
      A = TypeVar('A', str, bytes)  # Must be str or bytes

    ....
    def __init__(self, name, *constraints, bound=None,
                 covariant=False, contravariant=False):
    ....

Ahora, si solo tuvieras

ThetaType = TypeVar('ThetaType')
XType = TypeVar('XType')

¿Estaría argumentando que los usos de ThetaType deberían considerarse usos de XType, a pesar de que se configuraron 2 tipos de letra diferentes? ¿Por qué agregar el boundargumento opcional automáticamente los contraería nuevamente? La fuente no exige la presencia de enlaces, o cualquier argumento al lado del nombre, de ninguna manera.

No creo que sea tarea de tipear / mypy inferir sus intenciones en las declaraciones de tipo , solo para verificar su código frente a sus intenciones de tipo declaradas . Si quiere que sean iguales, declare solo 1 TypeVar. Considerarlos iguales podría perder algún significado semántico si tuviera razones reales para tener 2.

Agregaré a eso boundpermite más flexibilidad que constraintscomo coincide en las subclases. Digamos que ha definido 4 subclases de int definidas por el usuario. Int1 (int), Int2, Int3, Int4 ... Ahora ha decidido particionar su código donde algunos de ellos solo deberían aceptar Int1 e Int2. Typevarint12 podría expresar algo así, a pesar de que todas sus subclases coinciden bound=int.

JL Peyret
fuente
Sí, los dos tipos son diferentes. Sin embargo, no creo que sea importante para esta pregunta.
Neil G
1
@NeilG, entonces tal vez debería modificar su pregunta para que el título y sus comentarios sobre su código particular que muestre este comportamiento inesperado indiquen por qué espera algo diferente. En este momento, no veo nada en el bloque de construcción TypeVar que indique por qué 2 tipos de letra deberían comportarse de la misma manera. Si la forma en que configura su código alrededor de TypeVar debe conducir a la equivalencia, explique eso, pero no lo ancle solo en TypeVar .
JL Peyret
Nunca dije que los dos tipos de letra diferentes deberían comportarse igual. Los errores muestran que cada typevar es incompatible con sí mismo. Es cierto que tal vez podría haber encontrado un MWE más pequeño, pero no quería invertir más tiempo en esto.
Neil G