应继承 abc.ABC 并定义 @abstractmethod,而非在 new 中拦截;因 ABCMeta.__call__ 已在实例化前检查抽象性,__new__ 不会被调用,手动拦截既多余又破坏语义、工具链支持与错误提示。

用 abc.ABC 就够了,__new__ 不该掺和这事
Python 里想让一个类只能被继承、不能直接实例化,标准且唯一推荐的做法是继承 abc.ABC 并至少定义一个 @abstractmethod。强行在 __new__ 里加判断不仅多余,还会破坏 ABC 的语义和工具链支持(比如 IDE 提示、isinstance 检查、abc.abstractmethod 的运行时校验)。
常见错误现象:TypeError: Can't instantiate abstract class X with abstract method y —— 这正是你想要的报错,说明 ABC 机制已生效;但如果自己在 __new__ 里 raise,这个错误类型就变成 TypeError 或 RuntimeError,且绕过了 ABC 的抽象方法检查逻辑。
- 抽象方法必须用
@abstractmethod装饰,哪怕只是pass - 子类只要没实现全部抽象方法,依然无法实例化,无需额外干预
-
abc.ABC是元类ABCMeta的便捷别名,本质靠元类拦截__call__实现禁止实例化
为什么不要在 __new__ 里做实例化拦截
__new__ 是对象创建的第一步,但它发生在 ABC 元类的检查之后 —— 换句话说,如果类本身是抽象的,__new__ 根本不会被调用。你加的逻辑永远不会执行,纯属幻觉防御。
更麻烦的是:一旦你给基类写了自定义 __new__,又没正确调用 super().__new__,子类可能连正常实例化都失败;或者你误判了调用上下文(比如把子类实例化也拦掉了),反而制造 bug。
- ABC 的禁止机制在类被调用时(即
X())由ABCMeta.__call__触发,早于__new__ - 写
__new__拦截会掩盖真正的抽象错误,导致调试困难 - 静态分析工具(如 mypy)只认
@abstractmethod和abc.ABC,不识别手写的__new__逻辑
正确写法:带抽象方法的 abc.ABC 基类
下面是最小可行示例,没有任何多余代码:
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
from abc import ABC, abstractmethod
<p>class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass</p><h1>下面这行会立即报错:TypeError: Can't instantiate abstract class Shape...</h1><h1>s = Shape()</h1><p>class Circle(Shape):
def <strong>init</strong>(self, radius: float):
self.radius = radius</p><pre class="brush:php;toolbar:false;">def area(self) -> float:
return 3.14159 * self.radius ** 2
c = Circle(2.0) # ✅ 正常工作
注意:area 方法必须加 @abstractmethod,光继承 ABC 不足以触发实例化拦截 —— Python 要求至少一个抽象成员才视为“真正抽象”。
真需要运行时控制?用 __init_subclass__ 更安全
极少数场景下,你可能想在子类定义时做检查(比如禁止某类继承、强制要求某个类属性),这时应优先考虑 __init_subclass__,而不是动 __new__ 或 __call__。
-
__init_subclass__在子类被创建时调用,时机可控、语义清晰 - 它不干扰实例化流程,也不影响 ABC 的抽象校验
- 若真要阻止某些子类被定义(而非实例化),这才是正道
抽象基类的核心契约就是“有抽象方法就不能实例化”,把这个契约交给 abc 模块管,比自己缝合 __new__ 可靠得多。容易被忽略的点是:抽象性由元类保证,不是靠某个方法是否存在或是否抛异常来模拟的。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










