首页 > 解决方案 > 子类装饰方法的类型不兼容 - python

问题描述

我收到一个错误

$ 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

标签: pythonpropertiespython-decoratorsmypytype-hinting

解决方案


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

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

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

推荐阅读