执行覆盖时如何在方法中获取正确的注释签名顺序

时间:2018-09-17 21:38:35

标签: python-3.6 mypy

我正在尝试对魔术方法和普通方法修复一些方法注释。例如,我有一些情况,例如:

```

class Headers(typing.Mapping[str, str]):
    ...

    def __contains__(self, key: str) -> bool:
        ...
        return False

    def keys(self) -> typing.List[str]:
        ...
        return ['a', 'b']

```

当我运行mypy somefile.py --disallow-untyped-defs时,出现以下错误:

error: Argument 1 of "__contains__" incompatible with supertype "Mapping" error: Argument 1 of "__contains__" incompatible with supertype "Container" error: Return type of "keys" incompatible with supertype "Mapping"

我了解的是,我需要使用@override装饰器重写方法,并且需要尊重继承的顺序。正确吗?

如果我的假设正确,那么在哪里可以找到父类的确切签名?

1 个答案:

答案 0 :(得分:0)

mypy上提问后,答案是:

  

子类化typing.Mapping[str, str],我假设该函数   包含中的自变量键的签名应与   通用类型?

包含不是通用方法-它定义为具有类型签名包含((自我,密钥:对象)-> bool)。您可以在typeshed上进行检查。之所以这样定义包含,是因为在{“ foo”:“ bar”}中执行类似1的操作在技术上是合法的。

  

将def 包含(自身,密钥)子类化到def 包含(自身,密钥:   在任何情况下,str)都是更具体的。更具体的子类型不   违反利斯科夫,不是吗?

覆盖函数时,可以使参数类型更通用,而返回类型更具体。也就是说,参数类型应该是协变的,而返回类型应该是协变的。

如果我们不遵守规则,最终可能会在代码中引入错误。例如:

class Parent:
    def foo(self, x: object) -> None: ...

class Child(Parent):
    def foo(self, x: str) -> None: ...

def test(x: Parent) -> None:
    x.foo(300)  # Safe if 'x' is actually a Parent, not safe if `x` is actually a Child.

test(Child())

因为我们打破了liskov,将Child的一个实例传递给测试最终导致引入了错误。

基本上,如果我对Any方法的key使用__contains__是正确的,并且mypy不会抱怨:

 def __contains__(self, key: typing.Any) -> bool:
    ...
    return False

您可以关注对话here