命名约定-Python抽象类-如何阻止实例化



我来自C#背景,该语言具有一些内置的"保护开发人员"功能。我知道Python采用了"我们都是成年人"的方法,并将深思熟虑和仔细编码的责任交给了开发人员。

也就是说,Python为私有实例变量建议了诸如前导下划线之类的约定。我的问题是,除了在文档字符串中指定类之外,是否有将类标记为抽象类的特定约定在python风格指南中,我没有看到任何特别提到抽象类命名约定的内容。

到目前为止,我能想到三种选择,但我不确定它们是否是好主意:

  1. 在类上方的文档字符串中指定它(可能会被忽略)
  2. 在类名中使用前导下划线(不确定这是否被普遍理解)
  3. 引发错误的抽象类上创建一个def __init__(self):方法(不确定这是否会对继承产生负面影响,比如如果您想调用基构造函数)

其中一个是好的选择,还是有更好的选择?我只是想确保其他开发人员知道它是抽象的,所以如果他们试图实例化它,他们应该为任何奇怪的行为承担责任。

如果您使用的是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.'

根据您的最后一句话,我会回答"只记录它"。任何人如果以文档规定的方式使用类,就必须为任何奇怪的行为承担责任。

Python中有一个抽象基类机制,但如果你的唯一目标是阻止实例化,我看不出有任何理由使用它。

我只是用前缀"abstract"来命名我的抽象类。例如AbstractDevice、AbstractPacket等

这很容易,也很切中要害。如果其他人选择继续实例化和/或使用以"抽象"开头的类,那么他们要么知道自己在做什么,要么就没有希望了。

这样命名它,也提醒我自己不要对深层抽象层次感到疯狂,因为把"抽象"放在很多类的前面也感觉很愚蠢。

在抽象方法中创建"abstract"类和raise NotImplementedError()

它不会阻止人们使用这个类,而且,以真正的鸭子打字的方式,它会让你知道你是否忽略了实现抽象方法。

在Python 3.x中,您的类可以从abc.ABC继承。这将使你的类不可实例化,如果你试图这样做,IDE会警告你

import abc
class SomeAbstractClass(abc.ABC):
    @abc.abstractmethod
    def some_abstract_method(self):
        raise NotImplementedError
    
    @property
    @abc.abstractmethod
    def some_abstract_property(self):
        raise NotImplementedError

PEP 3119首次提出了这一点。

强制执行是可能的,但却不符合语法。经过多年的C++编程,当我来到Python时,我也尝试过做同样的事情,我想,如果大多数人有更经典语言的经验,他们都会尝试这样做。元类可以完成这项工作,但无论如何,Python在编译时检查的东西很少。您的检查仍将在运行时执行。那么,如果只在运行时发现无法创建某个类,那么它真的那么有用吗?在C++(以及C#)中,您甚至不能编译创建抽象类的代码,这就是问题的关键——尽早发现问题。如果您有抽象方法,那么引发NotImplementedError异常似乎就足够了。注意:引发,不返回错误代码!在Python中,错误通常不应该是静默的,除非显式静默。记录。以抽象的方式命名类。仅此而已。

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

最新更新