我正在尝试使用具有默认行为的构造函数声明抽象类Referer
:所有子类必须初始化成员A
:
self.n
但是,我不想让from abc import ABCMeta
class A(object):
__metaclass__ = ABCMeta
def __init__(self, n):
self.n = n
类被实例化,因为它是一个抽象类。问题是,这实际上是允许的:
A
这可以产生任何错误,我希望它应该。
那么:如何在为构造函数定义默认行为时定义不可实例化的抽象类?
答案 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 结束