繁体   English   中英

如何在 Python 中为抽象类定义构造函数实现?

[英]How define constructor implementation for an Abstract Class in Python?

我正在尝试使用具有默认行为的构造函数声明抽象类A :所有子类都必须初始化成员self.n

from abc import ABCMeta

class A(object):
    __metaclass__ = ABCMeta

    def __init__(self, n):
        self.n = n

但是,我不想让A类被实例化,因为它是一个抽象类。 问题是,这实际上是允许的:

a = A(3)

这不会产生错误,而我希望它应该。

那么:如何在为构造函数定义默认行为的同时定义不可实例化的抽象类?

使__init__成为抽象方法:

from abc import ABCMeta, abstractmethod

class A(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def __init__(self, n):
        self.n = n


if __name__ == '__main__':
    a = A(3)

帮助:

TypeError: Can't instantiate abstract class A with abstract methods __init__

Python 3 版本:

from abc import ABCMeta, abstractmethod

class A(object, metaclass=ABCMeta):

    @abstractmethod
    def __init__(self, n):
        self.n = n


if __name__ == '__main__':
    a = A(3)

也有效:

TypeError: Can't instantiate abstract class A with abstract methods __init__

一个不太优雅的解决方案可能是这样的:

class A(object):
  def __init__(self, n):
    if self.__class__ == A:
      raise Exception('I am abstract!')
    self.n = n

用法

class B(A):
  pass
a = A(1)  # Will throw exception
b = B(1)  # Works fine as expected.

您还应该使用@abc.abstractmethod装饰器将方法定义为抽象方法。

您可以覆盖__new__方法以防止直接实例化。

class A(object):
    __metaclass__ = ABCMeta

    def __new__(cls, *args, **kwargs):
        if cls is A:
            raise TypeError(
                "TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
            )
        return object.__new__(cls)

输出:

>>> A()
Traceback (most recent call last):
  File "<ipython-input-8-3cd318a12eea>", line 1, in <module>
    A()
  File "/Users/ashwini/py/so.py", line 11, in __new__
    "TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
TypeError: TypeError: Can't instantiate abstract class A directly

您可以实现如下内容:

from abc import ABC
class A(ABC):
    def __init__(self, n):
        self.n = n
        super(A,self).__init__()

实例化这个类会抛出一个错误

我不想让 A 类被实例化,因为它是一个抽象类。 问题是,这实际上是允许的

Python 本身不提供抽象类。 'abc' 模块提供定义抽象基类的基础结构。

抽象类是包含一个或多个抽象方法的类。 在您的情况下,代码仍然是一个抽象类,应该提供“无法实例化抽象类”行为。

如果您不想允许,程序需要更正:即添加装饰器@abstractmethod。 下面的代码在python 3.6中执行

from abc import ABC, abstractmethod

class Myabs(ABC):

    def __init__(self, connection):
        self.connection = connection
        print("1. calling from base init : {}".format(self.connection))
        super(Myabs, self).__init__()
    @abstractmethod
    def fun1(self, val):
        pass

class D(Myabs):
    def fun1(self, val="hi"):
        print("calling from D: fun1")


object0 = Myabs('connection') # Python 3.6.9

输出:

ClassConcept/abs_class.py 回溯(最近一次调用最后一次):文件“ClassConcept/abs_class.py”,第 19 行,在 object0 = Myabs('connection') # Python 3.6.9 TypeError:无法用抽象实例化抽象类 Myabs方法乐趣1

进程以退出代码 1 结束

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM