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

时间:2013-02-20 05:03:31

标签: python naming-conventions abstract-class

我来自C#背景,其中语言内置了“保护开发人员”功能。我理解Python采用“我们都是成年人”的方法,并且要求开发人员仔细认真地编写代码。

也就是说,Python建议使用惯例作为私有实例变量的前导下划线。我的问题是,是否有一个特定的约定将类标记为抽象而不仅仅是在文档字符串中指定它?我没有在python样式指南中看到任何特别提及抽象命名约定的内容类。

到目前为止,我可以考虑3种选择,但我不确定它们是否是好主意:

  1. 在课程上方的文档字符串中指定它(可能会被忽略)
  2. 在班级名称中使用前导下划线(不确定这是否被普遍理解)
  3. 在抽象类上创建一个引发错误def __init__(self):方法(不确定这是否会对继承产生负面影响,就像要调用基础构造函数一样)
  4. 其中一个是好的选择还是有更好的选择?我只是想确保其他开发人员知道它是抽象的,所以如果他们试图实例化它们就应该对任何奇怪的行为承担责任。

5 个答案:

答案 0 :(得分:21)

如果您使用的是Python 2.6或更高版本,则可以使用标准库中的Abstract Base Class模块来强制抽象。这是一个例子:

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.'

答案 1 :(得分:5)

根据你的最后一句,我会回答“只记录它”。任何以文档所说的方式使用课程的人都必须对任何奇怪的行为承担责任。

Python中有一个abstract base class机制,但如果您的唯一目标是阻止实例化,我认为没有任何理由可以使用它。

答案 2 :(得分:2)

创建“抽象”类,并在抽象方法中使用return NotImplementedraise NotImplementedError

它不会阻止人们使用该类,但是以真正的鸭子打字方式,它只会在您尝试使用抽象方法时成为一个问题。

答案 3 :(得分:2)

我只是用前缀'Abstract'命名我的抽象类。例如。 AbstractDevice,AbstractPacket等

这很简单,也很重要。如果其他人选择继续实例化和/或使用以“抽象”一词开头的类,那么他们要么知道他们正在做什么,要么就知道他们没有希望。

这样命名,也可以提醒我自己不要沉溺于深层抽象层次结构,因为将“抽象”放在很多类的前面也会感觉很愚蠢。

答案 4 :(得分:0)

强制执行事情是可能的,而不是单一的。经过多年的C ++编程后,当我来到Python时,我也尝试过这样做,我想,如果他们有更多经典语言的经验,大多数人都会尝试这样做。元类可以完成这项工作,但无论如何,Python在编译时会检查很少的东西。您的检查仍将在运行时执行。那么,如果仅在运行时发现,是否无法创建某个真正有用的类?在C ++中(以及在C#中)你甚至无法编译创建抽象类的代码,这就是重点 - 尽早发现问题。如果你有抽象方法,那么提出NotImplementedError异常就足够了。注意:提高,不返回错误代码!在Python中,除非显式地静默,否则错误通常不应该是静默的。文档化。以一种说它是抽象的方式命名一个类。就是这样。

Python代码的质量主要通过与高级编译时类型检查语言中使用的方法完全不同的方法来确保。就个人而言,我认为动态类型的lngauges和其他动态之间最严重的区别。单元测试,覆盖率分析等。因此,代码的设计是完全不同的:一切都不是为了强制执行,而是为了尽可能简单地测试它们。