![](/img/trans.png)
[英]Parsing an arbitrary combination of args kwargs and defaults to signature keys
[英]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
文档还有一个部分解释Any
和object
之间的区别。
如果您甚至将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.