如何在Python中阻止无抽象方法的抽象基类实例化?
如何让无抽象方法的ABC类被mypy禁止直接实例化?
你目前通过强制子类实现__str__的方式达成需求,但有两种更优的方案可以选择:
方案1:手动标记抽象类属性
直接在抽象基类中设置__abstractmethods__为非空的冻结集合,不需要额外定义抽象方法。Python运行时和mypy都会将这类视为抽象类,禁止实例化;而子类继承后,只要没有未实现的抽象方法,这个集合会被自动清空,子类可以正常实例化。
from abc import ABC from attrs import frozen class Abstract(ABC): # 随便填一个不存在的方法名,标记类为抽象 __abstractmethods__ = frozenset({"_abstract_marker"}) def do_something(self) -> int: return 777 @frozen class Concrete1(Abstract): name: str some_field: float @frozen class Concrete2(Abstract): name: int some_field: str # mypy会报错:Cannot instantiate abstract class "Abstract" with abstract attribute "_abstract_marker" # Python运行时也会抛出TypeError a = Abstract()
方案2:复用attrs自动生成的方法作为抽象方法
利用attrs为冻结类自动生成的方法(比如__eq__、__hash__),将其标记为抽象方法。因为attrs会自动给子类实现这些方法,所以子类不需要手动编写代码,同时抽象基类会被禁止实例化。
from abc import ABC, abstractmethod from attrs import frozen class Abstract(ABC): def do_something(self) -> int: return 777 @abstractmethod def __eq__(self, other: object) -> bool: ... @frozen class Concrete1(Abstract): name: str some_field: float @frozen class Concrete2(Abstract): name: int some_field: str # mypy报错:Cannot instantiate abstract class "Abstract" with abstract method "__eq__" a = Abstract()
方案对比
- 方案1更通用,不依赖attrs或其他库,适合所有继承ABC的场景。
- 方案2更贴合你的使用场景,无需额外的标记字段,但如果子类不使用attrs,就需要手动实现对应的抽象方法。
内容的提问来源于stack exchange,提问作者OrenIshShalom
相关产品推荐
相关产品推荐

