gpt4 book ai didi

python - 没有抽象方法的抽象类在python中创建对象

转载 作者:太空狗 更新时间:2023-10-29 21:51:50 25 4
gpt4 key购买 nike

基本上,我知道抽象基类就像常规类一样被用作骨架类,但是强制抽象方法应该被子类/继承类覆盖,如果它有一个如下所示

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 它起作用了,我们真的可以创建一个没有抽象方法的抽象类对象吗?所以请让我知道这背后的关键点

最佳答案

来自 the docs :

A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.

相反,这意味着任何没有抽象方法或属性的类(如您的 AbstractClass)都可以被实例化。


如果您想禁止最顶层父类的实例化,您可以编写一个自定义类,在其 __new__ 中执行类型检查。方法:

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)
class EmptyAbstractClass(NonEmptyABC):
pass

class NonemptyAbstractClass(NonEmptyABC):
@abc.abstractmethod
def foo(self):
pass

class NonemptyChild(NonemptyAbstractClass):
def foo(self):
pass

NonemptyChild() # works because "foo" is an abstractmethod
EmptyAbstractClass() # throws TypeError because there are no abstractmethods

关于python - 没有抽象方法的抽象类在python中创建对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50099600/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com