基本上,我知道抽象基类与常规类一样被用作框架类,但强制要求抽象方法应该被子/继承类重写,如果它有下面的那样
Class AbstractClass(object):
__metaclass__ = abc.ABCMeta
@abstractmethod
def absmethod(self):
pass
class ChildClass(AbstractClass):
def absmethod(self):
print "Yeah!"
obj = ChildClass()
因此我们可以创建一个ChildClass
对象
我们知道我们无法实例化一个抽象类,因为它只是骨架,如果我们尝试将其实例化,我们将会收到错误
obj = AbstractClass()
*** TypeError: Can't instantiate abstract class AbstractClass with abstract methods absmethod
但是我发布这个StackOverflow
的实际问题是,如果我们使用abc.ABCMeta
创建一个抽象类,而没有抽象方法,我可以创建一个抽象类的实例,它不应该是案件(如果我错了,请纠正我)
Class AbstractClass(object):
__metaclass__ = abc.ABCMeta
obj = AbstractClass()
OOOPPPSS 它有效,我们实际上可以在没有抽象方法的情况下创建抽象类的对象吗?所以请让我知道这个
背后的关键点答案 0 :(得分:3)
来自the docs:
具有从
ABCMeta
派生的元类的类不可能 实例化,除非它的所有抽象方法和属性都是 重写的。
相反,这意味着任何没有抽象方法或属性的类都可以<{1}} 实例化。
如果要禁止实例化最顶层的父类,可以编写一个自定义类,在其__new__
方法中执行类型检查:
AbstractClass
class SubclassOnlyABC(object):
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kwargs):
if cls.__bases__ == (SubclassOnlyABC,):
msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
raise TypeError(msg)
return super(SubclassOnlyABC, cls).__new__(cls, *args, **kwargs)
您还可以编写一个class AbstractClass(SubclassOnlyABC):
pass
class ChildClass(AbstractClass):
pass
ChildClass() # works because it's a child class of an abstract class
AbstractClass() # throws TypeError because its parent class is "object"
方法来阻止没有抽象方法的类的实例化:
__new__
class NonEmptyABC(object):
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kwargs):
# check if ANY abstractmethod exists
for parentcls in cls.__mro__:
if any(getattr(attr, '__isabstractmethod__', False)
for attr in vars(parentcls).values()):
break
else:
msg = 'Abstract class {} cannot be instantiated'.format(cls.__name__)
raise TypeError(msg)
return super(NonEmptyABC, cls).__new__(cls, *args, **kwargs)
答案 1 :(得分:1)
由于Python是一种动态语言,强制类继承特定类的想法违背了duck typing。因此,Python中抽象类的用例非常有限,并且由于传统原因而提供更多。但是,如果您想在不声明虚拟方法的情况下阻止类的实例化,则可以
class AbstractClass(object):
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kwargs):
if cls is AbstractClass:
raise Exception('Abstract class cannot be instantiatied')
return object.__new__(*args, **kwargs)
答案 2 :(得分:0)
这是不使用ABC的解决方案。有关here
所需的特定情况的更多信息DB_CONNECTION
答案 3 :(得分:0)
我通常只用 __init__
声明基类的 @abc.abstractmethod
。
如果我的基类没有 __init__
,我会添加一个微不足道的。
像这样:
class AbstractClass(abc.ABC):
@abc.abstractmethod
def __init__(self):
pass
# other useful non-abstract methods...
class ChildClass(AbstractClass):
def __init__(self):
pass
if __name__ == '__main__':
child = ChildClass() # allowed
abstract = AbstractClass() # TypeError