[英]How define constructor implementation for an Abstract Class in Python?
I am trying to declare an abstract class A
with a constructor with a default behavior: all subclasses must initialize a member self.n
:我正在尝试使用具有默认行为的构造函数声明抽象类
A
:所有子类都必须初始化成员self.n
:
from abc import ABCMeta
class A(object):
__metaclass__ = ABCMeta
def __init__(self, n):
self.n = n
However, I do not want to let the A
class be instantiated because, well, it is an abstract class.但是,我不想让
A
类被实例化,因为它是一个抽象类。 The problem is, this is actually allowed:问题是,这实际上是允许的:
a = A(3)
This produces no errors, when I would expect it should.这不会产生错误,而我希望它应该。
So: how can I define an un-instantiable abstract class while defining a default behavior for the constructor?那么:如何在为构造函数定义默认行为的同时定义不可实例化的抽象类?
Making the __init__
an abstract method:使
__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)
helps:帮助:
TypeError: Can't instantiate abstract class A with abstract methods __init__
Python 3 version: 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)
Works as well:也有效:
TypeError: Can't instantiate abstract class A with abstract methods __init__
A not so elegant solution can be this:一个不太优雅的解决方案可能是这样的:
class A(object):
def __init__(self, n):
if self.__class__ == A:
raise Exception('I am abstract!')
self.n = n
Usage用法
class B(A):
pass
a = A(1) # Will throw exception
b = B(1) # Works fine as expected.
您还应该使用@abc.abstractmethod
装饰器将方法定义为抽象方法。
You can override __new__
method to prevent direct instantiation.您可以覆盖
__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)
Output:输出:
>>> 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
You can implement something like below :您可以实现如下内容:
from abc import ABC
class A(ABC):
def __init__(self, n):
self.n = n
super(A,self).__init__()
Instantiating this class would throw an error实例化这个类会抛出一个错误
I do not want to let the A class be instantiated because, well, it is an abstract class.
我不想让 A 类被实例化,因为它是一个抽象类。 The problem is, this is actually allowed
问题是,这实际上是允许的
Python on its own doesn't provide abstract classes. Python 本身不提供抽象类。 'abc' module which provides the infrastructure for defining Abstract Base Classes.
'abc' 模块提供定义抽象基类的基础结构。
Abstract classes are classes that contain one or more abstract methods.抽象类是包含一个或多个抽象方法的类。 In your case code still an abstract class that should provide "Abstract classes cannot be instantiated" behavior.
在您的情况下,代码仍然是一个抽象类,应该提供“无法实例化抽象类”行为。
If you don't want to allow, program need corrections: ie add decorator @abstractmethod.如果您不想允许,程序需要更正:即添加装饰器@abstractmethod。 Below code executed in python 3.6
下面的代码在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
output:输出:
ClassConcept/abs_class.py Traceback (most recent call last): File "ClassConcept/abs_class.py", line 19, in object0 = Myabs('connection') # Python 3.6.9 TypeError: Can't instantiate abstract class Myabs with abstract methods fun1
ClassConcept/abs_class.py 回溯(最近一次调用最后一次):文件“ClassConcept/abs_class.py”,第 19 行,在 object0 = Myabs('connection') # Python 3.6.9 TypeError:无法用抽象实例化抽象类 Myabs方法乐趣1
Process finished with exit code 1
进程以退出代码 1 结束
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.