Несовместимость типов для оформленного метода подкласса - python - PullRequest
0 голосов
/ 10 октября 2018

Я получаю сообщение об ошибке

$ 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 голосов
/ 19 октября 2018

Я думаю, вы имели в виду, что dec вернет Callable, а не T. Должно быть:

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

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