在抽象方法的主体中应该放置什么内容?
在抽象方法的主体中应该放置什么内容?
假设我有以下抽象类Foo
:
import abc class Foo(abc.ABC): @abc.abstractmethod def bar(self): raise NotImplementedError
在bar
方法的主体中应该放什么?
我看到很多代码都写了raise NotImplementedError
,就像上面展示的那样。然而,这似乎是多余的,因为任何没有实现bar
的子类在实例化时都会引发TypeError: Can't instantiate abstract class Foo with abstract methods bar
。
将bar
留空,像下面这样,符合Python的风格吗?
import abc class Foo(abc.ABC): @abc.abstractmethod def bar(self): ...
这是Python文档中关于抽象基类的写法,但我不确定这是否只是一个占位符还是实际的代码示例。
如果将bar
只写三个点(...
),这样做是否可以?那么何时应该使用NotImplementedError
?
在这段内容中,问题的原因是作者询问应该在抽象方法的主体中放置什么。解决方法是通过提供默认实现来允许子类调用super(),并提供了一个示例代码来说明这一点。此外,还提到了collections.abc类的源代码中的示例。还提到了链接中的MutableSet.add和MutableSet.discard方法会引发NotImplementedError异常。
以下是整理后的文章:
文档的目的是为您提供一个示例,您不必遵循这个示例。您可以提供一个默认实现;子类仍然可以使用super()来调用您的实现。这就是大多数collections.abc类所做的事情;请参阅源代码。
例如,Size类的__len__方法返回0:
class Sized(metaclass=ABCMeta): # ... def __len__(self): return 0
感谢提供的链接。MutableSet.add和MutableSet.discard确实会引发NotImplementedError异常,所以我猜我应该坚持这种约定,而不是使用...。
根据上述内容,问题的原因是作者不清楚在抽象方法的主体中应该放置什么。解决方法是提供一个默认实现,并允许子类调用super()来调用该实现。此外,还提供了一个示例代码来说明这一点,并提到了collections.abc类的源代码中的示例。还提到了链接中的MutableSet.add和MutableSet.discard方法会引发NotImplementedError异常。
在Python中,抽象方法是一种没有具体实现的方法,它只是一个接口,用于指示派生类必须实现该方法。当定义一个抽象方法时,通常会面临一个问题:在抽象方法的主体中应该放什么?
按照Martijn Pieters的说法,可以在适当的地方提供一个默认值。这意味着如果派生类没有实现该方法,那么将使用默认值。下面是一个示例:
class FooBar(abc.ABC): def foo(bar): """This method foos some bars""" raise NotImplementedError
在这个示例中,如果派生类没有实现`foo`方法,那么当调用该方法时,将会引发`NotImplementedError`异常。这是一种明确告诉用户必须覆盖该方法的方法。
根据Python官方文档的建议,还有一些其他的方法可以在抽象方法的主体中使用,包括:
1. 使用省略号(`...`)代替`raise NotImplementedError`。这种方法在官方的Python文档中的抽象基类的示例中有支持。
2. 只使用`pass`语句。这种方法也很常见,它表示不做任何操作。
3. 实际上,只使用文档字符串是足够的。因为任何方法都应该有文档字符串,所以这种方法比使用省略号或`pass`语句更加优雅。
有多种方法可以在抽象方法的主体中使用。选择合适的方法取决于具体的需求和个人的偏好。无论选择哪种方法,都应该明确地告诉用户该方法是抽象的,需要在派生类中进行实现。