Python:抽象类__init__

时间:2017-06-28 11:02:35

标签: python python-2.7 oop abstract-class

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

self.n

但是,我不想让from abc import ABCMeta class A(object): __metaclass__ = ABCMeta def __init__(self, n): self.n = n 类被实例化,因为它是一个抽象类。问题是,这实际上是允许的:

A

这可以产生任何错误,我希望它应该。

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

6 个答案:

答案 0 :(得分:17)

使__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__

答案 1 :(得分:3)

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

答案 2 :(得分:2)

一个不太优雅的解决方案可以是:

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.

答案 3 :(得分:2)

您可以覆盖__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

答案 4 :(得分:2)

您可以实现以下内容:

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

实例化此类会引发错误

答案 5 :(得分:0)

<块引用>

我不想让 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 fun1

进程以退出代码 1 结束