繁体   English   中英

mypy 似乎认为 (*args, **kwargs) 可以匹配任何函数签名?

[英]mypy seems to think that (*args, **kwargs) could match to any funtion signature?

mypy如何将里氏代换原则应用于*args, **kwargs参数?

我认为以下代码应该无法通过 mypy 检查,因为 C 不允许对Base C允许的一些f调用,但它实际上通过了。 这有什么原因吗?

from abc import ABC, abstractmethod
from typing import Any


class Base(ABC):
    @abstractmethod
    def f(self, *args: Any, **kwargs: Any) -> int:
        pass


class C(Base):
    def f(self, batch: int, train: bool) -> int:
        return 1

我还尝试删除*args**kwargs ,但都失败了。

Daniil在当前接受的答案中所说的不同,原因正是(*args: Any, **kwargs: Any)签名部分。

请查看mypy问题跟踪器上的相应讨论

我其实很喜欢这个想法,我已经多次看到这种混淆,虽然它有点不安全,但大多数时候人们写 (*args, **kwargs) 的意思是“不关心”,而不是“应该”为所有电话工作”。

[GVR] 同意,这是实用性胜过纯粹性的案例。

所以, mypy对 form 的函数给予特殊处理

# _T is arbitrary type
class _:
    def _(self, *args, **kwargs) -> _T: ...

并认为它们完全等同于Callable[..., _T]

是的,这当然违反了 LSP,但这是专门设计的,以允许声明带有“忽略我的参数”签名的函数。

要声明真正接受任意位置和关键字 arguments 的最广泛可能的 function,您应该在签名中使用object

这与*args**kwargs本身无关。 严格来说,这是因为您对两个注释都使用typing.Any

Any注释基本上是类型检查器的Jedi 思维技巧,其效果如下:

这些您正在寻找的类型。

不管怎样,总会过去的。

出于这个原因, typing文档特别建议尽可能多地使用object而不是Any ,当你想说类似"the broadest possible type" 的东西时。 当您遇到 Python 打字系统的限制时,应将Any保留作为最后的手段。

mypy文档还有一个部分解释Anyobject之间的区别。

如果您甚至将Any注释中的一个更改为object ,您将受到C.f的正确惩罚,并出现mypy[override]错误。

例子:

from typing import Any

class Base:
    def f(self, *args: object, **kwargs: Any) -> int:
        return 2

class C(Base):
    def f(self, batch: int, train: bool) -> int:  # now this is an error
        return 1

而将“任意数量的位置和关键字参数”“每个参数将始终通过类型检查”结合起来,本质上转化为“没有覆盖永远不会出错” (就参数而言)。

所以我建议使用object而不是Any everywhere ,除非你无法避免使用后者。

这些混淆是我认为将此构造命名为Any的选择如此不幸的原因之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM