在Python中是否可以创建抽象类?

456
如何在Python中创建一个抽象类或方法?
我尝试像这样重新定义`__new__()`:
class F:
    def __new__(cls):
        raise Exception("Unable to create an instance of abstract class %s" %cls)

但是现在,如果我创建一个从F继承的类G,就像这样:
class G(F):
    pass

然后,我也无法实例化G,因为它调用了其超类的__new__方法。

有没有更好的定义抽象类的方式?


3
是的,你可以使用 Python 的 abc(抽象基类)模块创建抽象类。这个网站会帮助你了解它:http://docs.python.org/2/library/abc.html。 - ORION
13个回答

3
 from abc import ABCMeta, abstractmethod

 #Abstract class and abstract method declaration
 class Jungle(metaclass=ABCMeta):
     #constructor with default values
     def __init__(self, name="Unknown"):
     self.visitorName = name

     def welcomeMessage(self):
         print("Hello %s , Welcome to the Jungle" % self.visitorName)

     # abstract method is compulsory to defined in child-class
     @abstractmethod
     def scarySound(self):
         pass

不错 @Shivam Bharadwaj,我也是这样做的。 - Muhammad Irfan

2

虽然回答有些晚,但是针对这里指向的另一个问题“如何创建抽象方法”,我提供以下解答。

# decorators.py
def abstract(f):
    def _decorator(*_):
        raise NotImplementedError(f"Method '{f.__name__}' is abstract")
    return _decorator


# yourclass.py
class Vehicle:
    def add_energy():
       print("Energy added!")

    @abstract
    def get_make(): ...

    @abstract
    def get_model(): ...

基类Vehicle仍然可以被实例化进行单元测试(与ABC不同),并且Pythonic的异常抛出也存在。是的,您还可以通过此方法方便地获取异常中的抽象方法名称。


我喜欢这个,但是我有一个疑问:抽象方法的契约不是必须在具体子类中实现吗?你的解决方案(令人钦佩)的简单性(测试的可能性是其优点的非平凡方面)意味着我可以提出这个问题:对我来说还不清楚abc模块的解决方案是否强制要求在具体子类中实现指定的抽象方法。注意,在2021年,addGas应该更改为类似于add_energy的内容... - mike rodent

-3
在您的代码片段中,您还可以通过在子类中提供__new__方法的实现来解决此问题,如下所示:
def G(F):
    def __new__(cls):
        # do something here

但这是一种hack方法,我建议你不要使用,除非你知道自己在做什么。对于几乎所有情况,我建议您使用abc模块,这是其他人在我之前建议的。

此外,当您创建一个新的(基础)类时,请将其作为object的子类,就像这样:class MyBaseClass(object):。我不知道它是否还有那么重要,但它有助于保持代码的风格一致性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接