没有抽象方法的抽象类在python中创建对象 [英] abstract classes without abstract methods creating objects in python

查看:21
本文介绍了没有抽象方法的抽象类在python中创建对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Basically, I knew that abstract base classes are used as skeleton classes just like regular classes, but enforces that abstract methods should be overridden by the child/inherited classes if it has one like below

Class AbstractClass(object):
    __metaclass__ = abc.ABCMeta

    @abstractmethod
    def absmethod(self):
        pass

class ChildClass(AbstractClass):
    def absmethod(self):
        print "Yeah!"

obj = ChildClass()

这样我们就可以像上面一样创建一个ChildClass的对象

So we can create an object of ChildClass as above

我们知道我们不能实例化一个抽象类,因为它只是一个骨架,如果我们尝试如下实例化它,我们会得到一个错误

We know we can't instantiate an abstract class as it meant to be just skeleton and we will get an error if we try to instantiate it as below

obj = AbstractClass()

*** TypeError: Can't instantiate abstract class AbstractClass with abstract methods absmethod

但是我关于发布这个 StackOverflow 的实际查询是,如果我们使用 abc.ABCMeta 创建一个抽象类,没有抽象方法,我可以创建一个实例不应该是这种情况的抽象类(如果我错了,请纠正我)

But what my actual query about posting this StackOverflow is if we create an abstract class by using abc.ABCMeta, without abstract methods, I can able to create an instance of the abstract class which should not be the case(correct me if I am wrong)

Class AbstractClass(object):
    __metaclass__ = abc.ABCMeta

obj = AbstractClass()

OOOPPPSS 成功了,我们真的可以创建一个没有抽象方法的抽象类的对象吗?所以请让我知道这背后的关键点

OOOPPPSS it worked, we can actually create an object of abstract classes without abstract methods? So please let me know the key points behind this

推荐答案

来自 文档:

具有从 ABCMeta 派生的元类的类不能除非它的所有抽象方法和属性都被实例化被覆盖.

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

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

Conversely, this means that any class with no abstract methods or properties like your AbstractClass can be instantiated.

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

If you want to disallow instantiation of the topmost parent class, you can write a custom class that performs a type check in its __new__ method:

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__ 方法来防止实例化没有抽象方法的类:


You can also write a __new__ method that prevents instantiation of classes with no abstract methods:

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中创建对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆