只有在特定的情况下,对于特定的子类才具有强制属性/变量

2024-04-26 18:43:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个具有“强制”属性的抽象类:

class PMixin(ABC):

    @property
    @abstractmethod
    def progressbar_step(self):
        raise NotImplementedError

只有在特定情况下才可能有强制属性,而不是所有子类别。你知道吗

我使用多重继承

class A(PMixin, B)

从B继承也不是强制性的,否则是强制性的。你知道吗

如果不是B的子类,则A从PMixin继承all

如果它也从B继承,则不需要progressbar\u步骤。你知道吗

我可以声明:progressbar_step=None,在PMixin 如果不是从B继承的,则重写,并解决问题,如

class PMixin(ABC):
  progressbar_step = None

class A(PMixin)
  progressbar_step = 5

class A2(PMixin, B)
 ....

但我想得到一个警告,在哪种情况下有一个值,例如a; 它只是一种编码“安全”机制


Tags: selfnone属性defstep情况抽象类property
2条回答

对于<;3.6的python版本,您可以定义一个自定义的meta类来PMixin

class PMixinMeta(type):
    def __new__(mcs, names, bases, body):
        klass = super().__new__(mcs, names, bases, body)
        if issubclass(klass, B):  # 'if B in bases' is also ok 
            klass.progressbar_step = None
        return klass

但是,由于ABC也使用自定义的元类,如果将PMixinMeta定义为PMixin的元并从ABC继承,则会发生元类冲突。你知道吗

因此需要创建一个中间元类来解决冲突。你知道吗

from abc import ABCMeta

class PMixinAbcMeta(ABCMeta, PMixinMeta):
    pass

然后将PMixinAbcMeta定义为PMixin的元类

from abc import abstractmethod

class PMixin():
    __metaclass__ = PMixinAbcMeta
    @property
    @abstractmethod
    def progressbar_step(self):
        raise NotImplementedError

注意:只有在初始化(使用__init__)一个子类PMixin的实例时,才会出现异常。你知道吗

如果希望在生成时接收异常,PMixinMeta应该如下所示:

class PMixinMeta(type):
    def __new__(mcs, names, bases, body):
        klass = super().__new__(mcs, names, bases, body)
        if issubclass(klass, B):
            klass.progressbar_step = None
        else:
            if 'progressbar_step' not in body:
                raise ValueError('must have a progressbar_step method')
        return klass

意思是现在:

class A(PMixin):
    pass

将引发异常,而不仅仅是:

A()

这里有一个使用^{}的解决方案,在python3.6中提供。每当PMixin被子类化时,就会调用它,我们可以使用它从满足条件的子类中删除abstractmethod。你知道吗

from abc import ABC, abstractmethod

class B:
    pass

class PMixin(ABC):
    @property
    @abstractmethod
    def progressbar_step(self):
        raise NotImplementedError
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        if issubclass(cls, B):
            print('is subclass')
            print(cls.progressbar_step)
            cls.progressbar_step = None

class A(PMixin):  # Will raise error
        pass

class C(PMixin, B):  # No error
    pass

如果希望在子类PMixin时发出警告,而不是在尝试实例化该子类的对象时发出警告,可以选中__init_subclass__中的cls.progressbar_step.__isabstractmethod__,并适当地发出警告。你知道吗

相关问题 更多 >