Python 抽象类 - 如何防止实例化?
我之前是用C#的,在那个语言里有一些“保护开发者”的功能。而Python的做法则是“我们都是成年人”,把责任放在开发者身上,让他们认真思考和小心编码。
不过,Python建议一些约定,比如用一个下划线开头来表示私有实例变量。我的问题是,除了在文档字符串中说明之外,还有没有其他特别的约定来标记一个类为抽象类? 我在Python的风格指南中没有看到关于抽象类命名约定的具体内容。
我目前能想到三种选择,但不确定这些主意是否好:
- 在类的上方的文档字符串中说明(可能会被忽视)
- 在类名中使用一个下划线开头(不确定这是否被大家普遍理解)
- 在抽象类中创建一个
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.'