我应该把什么放在Python中的抽象方法体中

ost*_*ach 6 python abstract-class python-3.x

说我有以下抽象类Foo:

import abc

class Foo(abc.ABC):

    @abc.abstractmethod
    def bar(self):
        raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)

我该怎么把这个bar方法放在身体里?

我看到了很多代码raise NotImplementedError,如上所示.但是,这似乎是多余的,因为任何未实现的子类bar都会引发TypeError: Can't instantiate abstract class Foo with abstract methods bar它实例化的时间.

将Pythonic bar留空是否如下:

import abc

class Foo(abc.ABC):

    @abc.abstractmethod
    def bar(self):
        ...
Run Code Online (Sandbox Code Playgroud)

这是在抽象基类的Python文档中所做的,但我不确定这只是占位符还是如何编写代码的实际示例.

如果bar只留下三个点(...),我应该何时使用NotImplementedError

Mar*_*ers 8

文档的目的是给你一个例子.你不必遵循它.

你可以提供默认值; 子类仍然可以super()用来调用你的实现.这就是大多数collections.abc班级所做的事情; 看到源代码.

Size例如,返回0__len__:

class Sized(metaclass=ABCMeta):
    # ...
    @abstractmethod
    def __len__(self):
        return 0
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的链接。[MutableSet.add](https://hg.python.org/cpython/file/3.5/Lib/_collections_abc.py#l508)和[MutableSet.discard](https://hg.python.org/cpython/file /3.5/Lib/_collections_abc.py#l513)确实会引发`NotImplementedError`,所以我想我应该坚持使用该约定,而不是`...`。 (2认同)

Neu*_*ron 7

正如Martijn Pieters 所说,在默认值有意义的地方提供默认值。

如果您想告诉用户他们绝对应该覆盖它,请raise NotImplementedError像这样使用:

class FooBar(abc.ABC):
    @abstractmethod
    def foo(bar):
        """This method foos some bars"""
        raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)

引用

例外 NotImplementedError

该异常源自RuntimeError. 在用户定义的基类中,抽象方法在需要派生类重写该方法时,或者在开发该类以指示仍需要添加实际实现时,应引发此异常。


为了完整起见,以下是我在野外看到的其他一些事情(与官方建议相矛盾raise NotImplementedError):

  1. 不用加注,只需使用省略号 ( ...)即可。这有一些官方支持,因为抽象基类的官方 python 文档就是这样使用它的。
  2. 仅仅使用pass也很常见。
  3. 实际上,只使用文档字符串就足够了。恕我直言,任何方法都应该有一个文档字符串,所以这比 或 更...优雅pass