子类的修饰方法的类型不兼容-python

时间:2018-10-10 16:19:09

标签: python properties python-decorators mypy typehints

我遇到错误

$ mypy python.py
python.py:34: error: Signature of "fn" incompatible with supertype "B"

python.py在哪里

from typing import Callable, TypeVar, cast

T = TypeVar('T')


def dec(f: Callable[..., T]) -> T:
    def p(self):
        return getattr(self, '_' + f.__name__)

    return cast(T, property(p))


class X:
    pass


class Y(X):
    pass


class A:
    _fn = Y()


class B(A):
    @dec
    def fn(self) -> X:
        return X()


class C(B):
    @dec
    def fn(self) -> Y:
        return Y()

在这里,装饰器dec可以做两件事

  • 将相应方法升级为属性
  • 将调用重定向到名称带有附加下划线的属性

我不明白为什么mypy无法确定Y是从X继承的。如果将-> Y替换为-> X,或者移除装饰器,也不会出错。

我已经尝试过使用mypy 0.630和Python 3.5.2、3.6.6和3.7.0

编辑如评论中所指出,最初发布的A._fn的类型与C.fn不兼容。我已编辑A._fn来解决此问题。错误没有改变。

编辑某些上下文-A是一个看起来更像

的配置架构类
class A:
     def __init__(self, **kwargs):
         for k, v in kwargs.items():
             setattr(self, '_' + k, v)

,我们希望用户像c = C(fn=Y()); c.fn # gives a Y一样使用它。最初,问题以A_.fn作为返回Y()方法。更正此错误不会影响该错误

编辑我已将此问题作为mypy错误https://github.com/python/mypy/issues/5836

1 个答案:

答案 0 :(得分:0)

我认为您的意思是dec将返回Callable而不是T。 应该是:

def dec(f: Callable[..., T]) -> Callable[..., T]:
    def p(self):
       return getattr(self, '_' + f.__name__)

    return cast(Callable[..., T], property(p))