gpt4 book ai didi

python - 如果我在类方法中只分配两个泛型类型变量中的一个,为什么 mypy 会出错?

转载 作者:行者123 更新时间:2023-12-05 04:20:40 25 4
gpt4 key购买 nike

(python 3.10.6,mypy 0.990)

以下示例均被mypy接受:

from typing import Generic, TypeVar

T = TypeVar('T')
class Maybe(Generic[T]):
def __init__(self, val: T):
self._val = val

@classmethod
def empty(cls):
return cls(None)
from typing import Generic, TypeVar

U = TypeVar('U')
V = TypeVar('V')
class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def empty(cls):
return cls(None, None)
from typing import Generic, TypeVar

U = TypeVar('U')
V = TypeVar('V')
class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def both(cls, val: U, b: V):
return cls(val, b)

但是这种情况会返回以下错误:错误:“Example”的参数 2 具有不兼容的类型“None”;预期的“V”[arg-type]

from typing import Generic, TypeVar

U = TypeVar('U')
V = TypeVar('V')
class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def first(cls, val: U):
return cls(val, None)

似乎 mypy 接受绑定(bind)通用输入到类型变量,接受绑定(bind)具体值以推断类型变量,但不允许混合绑定(bind)和推断类型变量。怎么回事?

最佳答案

tl;dr 如果我调用 type(Example(0, 0)).first(0) 会怎样?在那种情况下,我们不能将 cls 推断为 type[Example[int, None]]

漫无边际的解释

在 Python 中调用类通常不是类型安全的。前两个示例实际上允许类型错误,因为我可以将它们子类化并更改 __init__。此类型检查但在运行时失败:

class Maybe1(Maybe[int]):
def __init__(self):
super().__init__(0)

Maybe1.empty()

好吧,那如果我们让 Maybe @final 呢?然后 Maybe1 无法定义,问题就消失了。或者是吗?我们会回到这个问题上。

关于 Example,如果 cls 被键入为封闭类,则调用它是不安全的。所以我们可以调用 Example

class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def first(cls, val: U) -> Example[U, None]:
return Example(val, None)

或将 cls 作为函数输入

class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def first(
cls: Callable[[U, None], Example[U, None]],
val: U
) -> Example[U, None]:
return cls(val, None)

如果您希望子类的 Example1.first 生成 Example1,显然这些都不起作用。我认为 Python 缺少 HKTs 禁止正确输入。它可能看起来像

# not valid Python

E = TypeVar("E", bound=Example)

class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def first(cls: Callable[[U, None], E[U, None]], val: U) -> E[U, None]:
return cls(val, None)

don't believe Python 3.11 中的 Self 在这里提供帮助

we reject using Self with type arguments

我们提到了@final,那如果我们@final Example呢?

@final
class Example(Generic[U, V]):
def __init__(self, a: U, b: V):
self._a = a
self._b = b

@classmethod
def first(cls, val: U) -> Example[U, None]:
return cls(val, None)

这是我们恢复错误的地方。要求 Python 将 Example.first(0) 中的 Example 推断为 Example[int, None] 是合理的,但是如果我们这样做呢? 类型(例子(0, 0)).first(0)?那么我们不能将type(Example(0, 0))推断为Example[int, None],所以我们不能将其推断为Example[int , 无] 在所有情况下。

关于python - 如果我在类方法中只分配两个泛型类型变量中的一个,为什么 mypy 会出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74417503/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com