如何根据基类方法是否存在而有条件地重写Python中的基类方法?

2024-05-13 17:35:25 发布

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

我有一个类BasicEvidenceTargetSchedulableSoma。有时我从SchedulableSoma, BasicEvidenceTarget继承,有时仅从SchedulableSoma继承。当我从SchedulableSoma, BasicEvidenceTarget继承时,我希望SchedulableSoma重写方法BasicEvidenceTarget.inject_basic_evidence。这样做的好方法是什么?在

覆盖如下所示:

class SchedulableSoma(SchedulableCluster, Soma):
    # This is a possible overload of this method in BasicEvidenceTarget.
    def inject_basic_evidence(self, *args, **kwargs):
        super().inject_basic_evidence(*args, **kwargs)
        self.ask_for_reschedule()

现在我无条件地重写基类方法,因此,如果基类方法不存在,则存在一些方法污染:如果调用重写,则调用super将失败。最好有条件地生成覆盖。在

我觉得有一个__prepare_subclass__魔法可能会起作用,但我不确定具体怎么做。在


Tags: 方法selfbasicargsthis基类kwargsclass
3条回答

我认为这个问题可以通过不同的继承模式来解决。利用你的想法:

class YourClass(SchedulableSoma, BasicEvidenceTarget):
    def inject_basic_evidence(self, *args, **kwargs):
        if isinstance(self, BasicEvidenceTarget):
            BasicEvidenceTarget.inject_basic_evidence(self, *args, **kwargs)
        else:
            super().inject_basic_evidence(*args, **kwargs)
        self.ask_for_reschedule()

或者

^{pr2}$

在定义继承它的类时,可以使用工厂函数生成适当的类。这只是一个草图:

def makeSubclass(otherclass):
    class MixedClass(otherclass):
        if otherClass == BasicEvidenceTarget:
            def inject_basic_evidence(...):
                # ...
        elif otherClass == WhateverOtherClass:
            def some_other_method(...):
                # ...

然后你会:

^{pr2}$

另一种可能是简单地在SchedulableSoma中定义所有方法,但在其中包含检查,如果当前实例没有从适当的类继承,则会引发异常。比如:

class SchedulableSoma(object):               
    def inject_basic_evidence(self, *args, **kwargs):
        if not isinstance(self, BasicEvidenceTarget):
            raise TypeError("Cannot call inject_basic_evidence unless you inherit from BasicEvidenceTarget")

    def some_other_method(self, *args, **kwargs):
        if not isinstance(self, SomeOtherClass):
            raise TypeError("Cannot call some_other_method unless you inherit from SomeOtherClass")

    # similar checks for other classes

这样,对inject_basic_evidence的调用将立即失败,并显示一条更具体的错误消息,而不是在{}调用中失败,并显示一条更模糊的关于“super object has no attribute”之类的消息。在

最终,您可能需要考虑是否有一种更健壮的方法来构建类层次结构。根据某些其他类是否也出现在继承层次结构中,让类改变自己的行为有点不可思议,而且它可能会混淆用户或导致类之间的不可预见的交互。在

在类定义时,如果没有funcy元类业务,您试图做的事情是不可能的。这可以在实例创建时使用以下代码完成:

class SchedulableSoma(SchedulableCluster, Soma):
    def __init__(self,*args,**kwargs):
        super().__init__(self,*args,**kwargs)
        if hasattr(self,"inject_basic_evidence"):
             def inject_basic_evidence(*args, **kwargs):
                 super().inject_basic_evidence(*args, **kwargs)
                 self.ask_for_reschedule()
             self.inject_basic_evidence = inject_basic_evidence

注意:如果SchedulableSoma的子类重写inject_basic_evidence

相关问题 更多 >