【问题标题】:`__subclasshook__` on inherited abstract classes in Python?`__subclasshook__` 在 Python 中继承的抽象类上?
【发布时间】:2021-12-10 21:08:46
【问题描述】:

我想知道如何才能最好地在 Python 中的抽象类层次结构上定义 __subclasshook__。假设我有一个接口,以及一个继承自该接口的 ABC。这样的事情可以吗?

import abc
from typing import IO

class IFileHandler(metaclass=abc.ABCMeta):
  def import(self) -> bytes:
    raise NotImplementedError

  def export(self) -> IO:
    raise NotImplementedError

  @classmethod
  def __subclasshook__(cls, subclass):
    return all((
      hastattr(subclass, 'import'),
      callable(getattr(subclass, 'import', None)),
      hasattr(subclass, 'export'),
      callable(getattr(subclass, 'export', None))
    )) or NotImplemented


class FileBase(IFileHandler, metaclass=abc.ABCMeta):
  def __init__(self):
    ... 

  def import(self):
    ...

  def export(self):
    raise NotImplementedError

  def another_method(self):
    ...

  @classmethod
  def __subclasshook__(cls, subclass):
    if super().__subclasshook(subclass) is NotImplemented:
      return NotImplemented
    return all((
      hasattr(subclass, '__init__'),
      callable(getattr(subclass, '__init__', None)),
      hasattr(subclass, 'another_method'),
      callable(getattr(subclass, 'another_method', None)),
    )) or NotImplemented


class ConcreteFileClass(FileBase):
  def export(self):
    ...

有没有更优雅的方式来调用超类'__subclasshook__ 并处理其结果?我在这里完全找错树了吗?任何见解将不胜感激,谢谢!

【问题讨论】:

  • 使用abc.ABCMetafrom abc import ABCMeta
  • 抱歉,我只是从内存中输入一些基本代码,因此忘记导入它。我将编辑 OP 以更正它。
  • 据我所知,OP 就是你 :) “帖子”就是帖子。

标签: python oop subclassing abc


【解决方案1】:

您可以考虑使用abstractmethod 装饰器,而不是重新发明abc 的整个机制:

from abc import ABCMeta, abstractmethod
from typing import IO

class IFileHandler(metaclass=ABCMeta):
    @abstractmethod
    def import(self) -> bytes:
        pass

    @abstractmethod
    def export(self) -> IO:
        pass

class FileBase(IFileHandler):
    @abstractmethod
    def __init__(self):
        pass

    def import(self):
        ...

    def export(self):
        ...

    @abstractmethod
    def another_method(self):
        pass

您不需要将metaclass 显式提供给FileBase,因为继承已经处理了它。 abstractmethod 不允许在没有具体实现的情况下实例化子类。不要在存根方法中提高NotImplementedError,而是使用Ellipsis (...) 或pass。这样子类就可以正确调用super().whatever而不会出错。

【讨论】:

    猜你喜欢
    • 2021-10-24
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多