确定 subclass 是否在 Python 中实现了基础 class 的方法

Determine if subclass has a base class's method implemented in Python

我有一个扩展基数 class 的 class。实例化后,我想检查 subclass 是否具有从其基础实现的 classes 之一,但我不确定最好的方法。 hasattr(self, '[method]') returns 来自 super 的方法如果没有被 child 实现,所以我试图区分它们。

这是一个例子:

class Base :
   def __init__ ( self,) :
       pass
   
   def fail (self,) :
       pass

# Now create the subclass w/o .fail
class Task ( Base ) :
    def __init__ ( self, ):
         print( hasattr( self, 'fail' ) ) # < returns True

Task() 被实例化时它打印 True 因为 TaskBase 继承了 .fail。但在这种情况下,我想知道 Task 没有 实现 .fail,所以我想以某种方式返回 False。好像我在寻找类似 isimplemented( self, 'fail' ) 的东西。我错过了什么?

IIUC,可以查看super().fail == self.fail

class Base:
    def __init__(self):
        pass
   
    def fail(self):
        pass

class Task(Base):
    def __init__(self):
        print(super().fail == self.fail)
    
class Task2(Base):
    def __init__(self):
        print(super().fail == self.fail)
    
    def fail(self):
        # Override
        pass

输出:

t1 = Task()
# True

t2 = Task2()
# False

不确定我是否理解正确,但您可以检查 fail 方法是否在 class 的 vars 中,但没有继承到主要的 class .

所以你可以试试:

class Base:
    def __init__(self):
        print(self.__dir__())
   
    def fail(self):
        pass

class Task(Base):
    def __init__(self):
        print('fail' not in vars(Task))
    
class Task2(Base):
    def __init__(self):
        print('fail' not in vars(Task2))
    
    def fail(self):
        # Override
        pass
    
t1 = Task()
t2 = Task2()

输出:

True
False

或使用__dict__:

...
class Task(Base):
    def __init__(self):
        print('fail' not in Task.__dict__)
    
class Task2(Base):
    def __init__(self):
        print('fail' not in Task2.__dict__)
    
    def fail(self):
        # Override
        pass
...

我不确定我是否理解正确,但听起来您可能正在寻找抽象基础类。 (文档 here, tutorial here。)如果您在继承自 abc.ABC 的基 class 中指定 abstractmethod,则尝试实例化子 class 将失败,除非subclass 覆盖抽象方法。

from abc import ABC, abstractmethod

class Base(ABC):
    @abstractmethod
    def fail(self):
        pass

class Task(Base):
   pass
    
class Task2(Base):
    def fail(self):
        pass

# this raises an exception
# `fail` method has not been overridden in the subclass.
t1 = Task()

# this succeeds
# `fail` method has been overridden in the subclass.
t2 = Task2()

如果您希望在 class 定义 时间而不是 实例实例化 时间进行检查,另一种选择是在你的基础 class 中写一个 方法,每次你 subclass 你的基础 class 或你 subclass a class 时都会调用它继承自您的基地 class。 (你不必在 __init_subclass__ 中引发异常——你可以只向 class 添加一个 fail_overriden 布尔属性,或者做任何你喜欢的事情。)

class Base:
    def fail(self):
        pass

    def __init_subclass__(cls, **kwargs):
        if cls.fail == Base.fail:
            raise TypeError(
               'Subclasses of `Base` must override the `fail` method'
            )
        super().__init_subclass__(**kwargs)


# this class definition raises an exception
# because `fail` has not been overridden
class Task(Base):
    pass


# this class definition works fine.
class Task2(Base):
    def fail(self):
        pass

如果您只是想让每个实例都告诉您 fail 是否在其子 class 中被覆盖,您可以这样做:

class Base:
    def __init__(self):
        print(type(self).fail != Base.fail)

    def fail(self):
        pass

class Task(Base):
   def __init__(self):
       super().__init__()
    
class Task2(Base):
    def __init__(self):
       super().__init__()

    def fail(self):
        pass

t1 = Task() # prints "True"
t2 = Task2() # prints "False"