【问题标题】:Can I mark a class abstract even if all its methods are implemented?即使实现了所有方法,我可以标记类摘要吗?
【发布时间】:2021-12-06 14:10:53
【问题描述】:

有没有办法将 python 类标记为抽象或不可实例化,即使它的所有抽象方法都已实现?

class Component(ABC):
    @abstractmethod
    def operation(self) -> None:
        pass

class Decorator(Component): # I would like this class to be abstract
    def operation(self) -> None:
        print("basic operation")

我找到的唯一解决方法是在类中选择一些方法来同时具有实现和@abstractmethod 装饰器,但是python 需要子抽象类的派生来重新实现该方法。

这也可以通过让子类调用 super() 来解决,但 pylint 抱怨这是一个无用的调用。

class Component(ABC):
    @abstractmethod
    def operation(self) -> None:
        pass

class Decorator(Component): # I would like this class to be abstract
    @abstractmethod
    def operation(self) -> None:
        print("basic operation")

class ConcreteDecorator(Decorator): 
    def operation(self) -> None: # python makes child class re-implement
        super().operation()  # pylint complains about useless super delegation

有没有更好的方法来做到这一点?
我尝试使用带有实现和@abstractmethod 装饰器的方法,但是派生类需要重新实现。 我正在寻找“编译时”的解决方案,而不是运行时错误。

【问题讨论】:

  • 如果所有的方法都实现了,为什么它被认为是不可实例化的?您能否就您要解决的实际问题提供一些背景信息?
  • 当然,例如 GOF 装饰器模式中的 BaseDecorator。它转发所有调用作为派生自它的具体装饰器的基础,但单独使用它是错误的。在 Java/C++/C# 中可以做到这一点
  • 听起来像是pylint 问题——你不能让它静音吗?顺便说一句,@abstractmethod 是装饰器,而不是注释(这是完全不同的东西)。
  • 我同意这是pylint 的问题,而不是你的问题。但从另一个角度来看,抽象类与其说是关于防止实例化,不如说是关于确保实例化是安全的。如果您不希望 Decorator 实例化,请对您不希望其他人使用的任何其他类执行您想要的操作:将其命名为 _Decorator,将其记录为私有实现细节,并要求其他人创建子类。如果Decorator.operation 足够了,那么让子类化器决定他们是否想做更多的事情,而不是简单地通过覆盖它来调用它。
  • 如果你真的想实例化一个类,绕过它的抽象性已经很简单了,所以如果真的不需要的话,不要向后弯腰使一个类抽象。

标签: python abstract-class abc


【解决方案1】:

创建一个覆盖__new__ 函数的辅助类,以检查cls.__bases__ 是否包含自身。

class UnInstantiable:
    def __new__(cls, *args, **kwargs):
        if __class__ in cls.__bases__:
            raise TypeError(f"Can't instantiate un-instantiable class {cls.__name__}")

        return super().__new__(cls)

用法:

# class Decorator(Component):                # Add UnInstantiable base class
class Decorator(Component, UnInstantiable):  # like this
    def operation(self) -> None:
        print("basic operation")


Decorator()  # TypeError: Can't instantiate un-instantiable class Decorator

【讨论】:

  • 我在 if 上得到了未定义的变量 __class__。如果 cls.__class__ 应该是这样吗?
  • 你使用的是哪个版本的 Python?
  • 3.8.1 with pylance on VS code
  • 这是实际的运行时错误还是 IntelliSense 错误?
  • 哦,现在我知道它只是 IntelliSense。类型错误已成功引发。
猜你喜欢
  • 2015-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 2011-07-13
  • 1970-01-01
相关资源
最近更新 更多