Python 抽象类 - 如何防止实例化?

20 投票
6 回答
14252 浏览
提问于 2025-04-17 16:27

我之前是用C#的,在那个语言里有一些“保护开发者”的功能。而Python的做法则是“我们都是成年人”,把责任放在开发者身上,让他们认真思考和小心编码。

不过,Python建议一些约定,比如用一个下划线开头来表示私有实例变量。我的问题是,除了在文档字符串中说明之外,还有没有其他特别的约定来标记一个类为抽象类? 我在Python的风格指南中没有看到关于抽象类命名约定的具体内容。

我目前能想到三种选择,但不确定这些主意是否好:

  1. 在类的上方的文档字符串中说明(可能会被忽视)
  2. 在类名中使用一个下划线开头(不确定这是否被大家普遍理解)
  3. 在抽象类中创建一个def __init__(self):方法,并抛出一个错误(不确定这是否会对继承产生负面影响,比如如果你想调用基类的构造函数)

这三种选择中有哪个是好主意吗?还是有更好的方法?我只是想确保其他开发者知道这个类是抽象的,如果他们尝试实例化它,就要对任何奇怪的行为负责。

6 个回答

3

我通常会给我的抽象类起个名字,加上前缀“Abstract”。比如,AbstractDevice、AbstractPacket等等。

这样做简单明了。如果其他人选择去实例化或者使用一个以“Abstract”开头的类,那他们要么知道自己在做什么,要么就没救了。

这样命名也提醒我自己不要过于复杂地设计抽象层次,因为给很多类前面都加上“Abstract”听起来也很傻。

5

根据你最后一句话,我的回答是“就把它写下来”。任何以文档中不建议的方式使用这个类的人,都必须对出现的奇怪行为负责。

在Python中有一个抽象基类的机制,但如果你只是想阻止别人创建这个类的实例,我觉得没有必要使用它。

24

如果你使用的是Python 2.6或更高版本,可以利用标准库中的抽象基类模块来强制执行抽象性。下面是一个例子:

from abc import ABCMeta, abstractmethod

class SomeAbstractClass(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def this_method_must_be_overridden(self):
        return "But it can have an implementation (callable via super)."

class ConcreteSubclass(SomeAbstractClass):
    def this_method_must_be_overridden(self):
        s = super(ConcreteSubclass, self).this_method_must_be_overridden()
        return s.replace("can", "does").replace(" (callable via super)", "")

输出结果:

>>> a = SomeAbstractClass()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a = SomeAbstractClass()
TypeError: Can't instantiate abstract class SomeAbstractClass with abstract
methods this_method_must_be_overridden
>>> c = ConcreteSubclass()
>>> c.this_method_must_be_overridden()
'But it does have an implementation.'

撰写回答