简体   繁体   English

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

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

How does mypy apply the Liskov substitution principle to *args, **kwargs parameters? mypy如何将里氏代换原则应用于*args, **kwargs参数?

I thought the following code should fail a mypy check since some calls to f allowed by the Base class are not allowed by C , but it actually passed.我认为以下代码应该无法通过 mypy 检查,因为 C 不允许对Base C允许的一些f调用,但它实际上通过了。 Are there any reasons for this?这有什么原因吗?

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

I also tried to remove either *args or **kwargs , both failed.我还尝试删除*args**kwargs ,但都失败了。

Unlike Daniil said in currently accepted answer, the reason is exactly (*args: Any, **kwargs: Any) signature part.Daniil在当前接受的答案中所说的不同,原因正是(*args: Any, **kwargs: Any)签名部分。

Please check the corresponding discussion on mypy issue tracker :请查看mypy问题跟踪器上的相应讨论

I actually like this idea, I have seen this confusion several times, and although it is a bit unsafe, most of the time when people write (*args, **kwargs) it means "don't care", rather than "should work for all calls".我其实很喜欢这个想法,我已经多次看到这种混淆,虽然它有点不安全,但大多数时候人们写 (*args, **kwargs) 的意思是“不关心”,而不是“应该”为所有电话工作”。

[GVR] Agreed, this is a case where practicality beats purity. [GVR] 同意,这是实用性胜过纯粹性的案例。

So, mypy gives a special treatment to functions of form所以, mypy对 form 的函数给予特殊处理

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

and considers them fully equivalent to Callable[..., _T] .并认为它们完全等同于Callable[..., _T]

Yes, this actually violates LSP, of course, but this was designed specially to allow declaring functions with signature "just ignore my parameters".是的,这当然违反了 LSP,但这是专门设计的,以允许声明带有“忽略我的参数”签名的函数。

To declare the broadest possible function that really accepts arbitrary positional and keyword arguments, you should use object in signature instead.要声明真正接受任意位置和关键字 arguments 的最广泛可能的 function,您应该在签名中使用object

This has nothing to do with *args or **kwargs per se.这与*args**kwargs本身无关。 The reason for this is strictly the fact that you used typing.Any for both annotations.严格来说,这是因为您对两个注释都使用typing.Any

The Any annotation is basically a Jedi mind trick for the type checker to the effect of: Any注释基本上是类型检查器的Jedi 思维技巧,其效果如下:

These are the types you were looking for.这些您正在寻找的类型。

No matter what, it will always pass.不管怎样,总会过去的。

For this reason, the typing documentation specifically recommends to use object as much as possible instead of Any , when you mean to say something like "the broadest possible type" .出于这个原因, typing文档特别建议尽可能多地使用object而不是Any ,当你想说类似"the broadest possible type" 的东西时。 Any should be reserved as the last resort, when you bump against the limits of the Python typing system.当您遇到 Python 打字系统的限制时,应将Any保留作为最后的手段。

The mypy docs also have a section explaining the difference between Any and object . mypy文档还有一个部分解释Anyobject之间的区别。

If you change even one of those Any annotations to object , you will be rightfully chastised by mypy with an [override] error for C.f .如果您甚至将Any注释中的一个更改为object ,您将受到C.f的正确惩罚,并出现mypy[override]错误。

Example:例子:

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

Whereas the combination of saying "any number of positional and keyword-arguments" together with "each argument will always pass the type check" essentially translates to "no override will ever be wrong" (in terms of arguments).而将“任意数量的位置和关键字参数”“每个参数将始终通过类型检查”结合起来,本质上转化为“没有覆盖永远不会出错” (就参数而言)。

So I would suggest using object instead of Any everywhere , unless you cannot avoid using the latter.所以我建议使用object而不是Any everywhere ,除非你无法避免使用后者。

These confusions are one of the reasons I think the choice to name this construct Any is so unfortunate.这些混淆是我认为将此构造命名为Any的选择如此不幸的原因之一。

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

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