Python abstract classes - how to discourage instantiation?
我来自C背景,在C背景中,语言具有一些内置的"保护开发人员"功能。我理解python采用了"我们都是成年人"的方法,并将开发人员的职责放在了仔细思考的代码上。
也就是说,python建议使用一些约定,比如私有实例变量的前导下划线。我的问题是,除了在docstrings中指定类之外,是否存在将类标记为抽象类的特定约定?在提到抽象类命名约定的Python风格指南中,我没有看到任何特别的内容。
到目前为止,我可以考虑3种选择,但我不确定它们是否是好主意:
其中一个是好的选择还是有更好的选择?我只是想确保其他开发人员知道它是抽象的,所以如果他们试图实例化它,他们应该为任何奇怪的行为承担责任。
如果您使用的是python 2.6或更高版本,那么如果您想强制实现抽象性,可以使用标准库中的抽象基类模块。下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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)","") |
输出:
1 2 3 4 5 6 7 8 9 | >>> 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.' |
号
根据你的最后一句话,我会回答"把它记录下来"。任何以文档所说的不必为任何奇怪行为承担责任的方式使用类的人。
在Python中有一个抽象的基类机制,但是如果您的唯一目标是不鼓励实例化,我看不出使用它的任何理由。
我只是用前缀"abstract"命名抽象类。例如,抽象设备、抽象包等。
这是最简单的,最关键的。如果其他人选择继续并实例化和/或使用以单词"abstract"开头的类,那么他们要么知道自己在做什么,要么根本没有希望。
因此命名它,也可以提醒我自己不要对深度抽象的层次结构发疯,因为将"抽象"放在许多类的前面也会让人觉得很愚蠢。
创建"abstract"类,并在抽象方法中使用
它不会阻止人们使用类,但以真正的duck输入方式,它只会在您尝试使用抽象方法时成为一个问题。
强制执行是可能的,但相当不合理。当我经过Python多年的C++编程后,我也尝试着做同样的事情,我想,大多数人都会尝试这样做,如果他们有更多的经典语言的经验。元类可以完成这项工作,但无论如何,Python在编译时检查的内容很少。您的检查仍将在运行时执行。因此,如果只在运行时发现,那么无法创建某个类真的那么有用吗?在C++中(也在C语言中),你甚至不能编译你的代码来创建一个抽象类,这就是问题的全部——尽可能早地发现问题。如果您有抽象方法,那么引发
Python代码的质量主要是通过与高级编译时类型检查语言中使用的方法截然不同的方法来保证的。我个人认为动态类型的lngauges和其他类型的lngauges之间最严重的区别。因此,代码的设计就大不一样了:所有的工作都不是为了强制执行,而是为了尽可能简单地测试它们。