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

问题描述 投票:0回答:3

在尝试更新我的代码以使其符合 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"

我的班级:

from abc import abstractmethod

from typing import Any


class MyClass(object):

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

我的文件.py:

class MyImplementation(MyClass):

[...]

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

        [...]

        return True

我肯定在这里做错了什么,但我不太明白是什么:)

任何指点将不胜感激。

python python-3.x type-hinting mypy python-typing
3个回答
20
投票
@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
签名,也许这个方法不应该真正位于超类中,或者您可能需要重新考虑您的类层次结构,或者给它们相同的签名。


-2
投票

您可以使用

Callable[..., Any]
type: ignore
来解决问题,如下所示。

from typing import Callable

class MyClass(object):
    deliver: Callable[..., bool]
    @abstractmethod
    def deliver(self, *args, **kwargs): # type: ignore
        raise NotImplementedError

-3
投票

也许你应该这样解决:

  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
    

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

© www.soinside.com 2019 - 2024. All rights reserved.