Python 3.6: Подпись {method} несовместима с супертипом {Class} - PullRequest
0 голосов
/ 23 июня 2018

При попытке обновить мой код до соответствия PEP-484 (я использую mypy 0.610) я столкнулся со следующим отчетом:

$ mypy mymodule --strict-optional --ignore-missing-imports --disallow-untyped-calls --python-version 3.6

myfile.py:154: error: Signature of "deliver" incompatible with supertype "MyClass"

MyClass:

from abc import abstractmethod

from typing import Any


class MyClass(object):

@abstractmethod
def deliver(self, *args: Any, **kwargs: Any) -> bool:
    raise NotImplementedError

myfile.py:

class MyImplementation(MyClass):

[...]

    def deliver(self, source_path: str,
                dest_branches: list,
                commit_msg: str = None,
                exclude_files: list = None) -> bool:

        [...]

        return True

Я определенно что-то делаю не так, но не могу понять, что:)

Любые указатели будут высоко оценены.

Ответы [ 2 ]

0 голосов
/ 30 мая 2019

Может быть, вы должны обойти это так:

  1. Определение абстрактного метода без аргументов:

    class MyClass:
        @abstractmethod
        def deliver(self) -> bool:
            raise NotImplementedError
    
  2. В реализациях получите все ваши данные от self:

    class MyImplementation(MyClass):
        def __init__(
                self,
                source_path: str,
                dest_branches: list,
                commit_msg: str = None,
                exclude_files: list = None
        ) -> None:
            super().__init__()
            self.source_path = source_path
            self.dest_branches = dest_branches
            self.commit_msg = commit_msg
            self.exclude_files = exclude_files
    
        def deliver(self) -> bool:
            # some logic
            if self.source_path and self.commit_msg:
                return True
            return False
    

Таким образом, вы будете иметь полностью совместимые объявления методов и сможете реализовать методы так, как вам хочется.

0 голосов
/ 23 июня 2018
@abstractmethod
def deliver(self, *args: Any, **kwargs: Any) -> bool:
    raise NotImplementedError

Это объявление не означает, что подклассы могут дать deliver любую подпись, которую они хотят. Методы подкласса deliver должны быть готовы принять любые аргументы, которые примет метод суперкласса deliver, поэтому ваш подкласс deliver должен быть готов принять произвольные позиционные или ключевые аргументы:

# omitting annotations
def deliver(self, *args, **kwargs):
    ...

У вашего подкласса deliver нет этой подписи.


Если предполагается, что все подклассы имеют одинаковую подпись deliver, которую вы написали для MyImplementation, то вам следует также поставить MyClass.deliver такую ​​же подпись. Если ваши подклассы будут иметь разные deliver подписи, возможно, этот метод на самом деле не должен быть в суперклассе, или, возможно, вам нужно переосмыслить иерархию классов или дать им одну и ту же сигнатуру.

...