Python 3.6:{方法}的签名与超级类型{Class}不兼容

时间:2018-06-23 16:42:11

标签: python python-3.x typing mypy

在尝试将我的代码更新为符合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 :(得分:4)

@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签名,则此方法可能实际上不应该在超类中,或者您可能需要重新考虑类层次结构或给它们相同的签名。

答案 1 :(得分:0)

也许您应该按照以下方式解决它:

  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
    

这样,您将拥有完全兼容的方法声明,并且仍然可以根据需要实现方法。