You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何未被@abstractmethod装饰的方法的__isabstractmethod__属性为True?

这是个挺有意思的问题,我先帮你理清正常情况下的行为,再分析你看到异常结果的可能原因。

首先,我们先明确几个关键知识点:

  • @abstractmethod 装饰器的核心作用是给被装饰的方法对象添加 __isabstractmethod__ = True 属性,以此标记它是抽象方法。
  • staticmethod 和 classmethod 都是描述符类,它们的 __isabstractmethod__ 属性是通过代理到包装的原始函数来实现的:如果包装的函数有 __isabstractmethod__ 属性就返回它的值,没有就返回 False。
  • 普通实例方法(比如你的 im)如果没被 @abstractmethod 装饰,本身是没有 __isabstractmethod__ 属性的,直接访问会抛出 AttributeError。

正常运行结果

用你给出的代码在 Python 3.3+ 的版本中运行,正确的输出应该是:

from abc import abstractmethod
class K:
    @staticmethod
    def sm(*args):
        pass
    @classmethod
    def cm(*args):
        pass
    @abstractmethod
    def am(*args):
        pass
    def im(*args):
        pass

K_dct = object.__getattribute__(K, '__dict__')
sm = K_dct['sm']
cm = K_dct['cm']
am = K_dct['am']
im = K_dct['im']

print(sm.__isabstractmethod__)  # False
print(cm.__isabstractmethod__)  # False
print(am.__isabstractmethod__)  # True
# print(im.__isabstractmethod__)  # 会抛出 AttributeError,因为普通函数没有这个属性

你看到非抽象方法 __isabstractmethod__ = True 的可能原因

  1. Python 版本的历史 bug
    在 Python 3.0 到 3.2 的早期版本中,staticmethod 和 classmethod 的 __isabstractmethod__ 属性实现存在问题,可能会错误地返回 True。如果你使用的是这些旧版本,升级到 Python 3.3+ 就能解决这个问题。

  2. 混淆了类和方法的 __isabstractmethod__ 属性
    你的类 K 因为包含抽象方法 am,所以类本身的 __isabstractmethod__ 属性会是 True(这是由 ABCMeta 元类自动设置的,用来标识这是一个抽象类)。如果你误把类的这个属性当成了某个方法的属性,就会产生误解。

  3. 间接触发了描述符的 __get__ 方法
    虽然你说“不要调用描述符的 __get__ 方法”,但如果不小心通过类或实例访问了方法(比如 K.sm 而不是直接从 __dict__ 取),会得到一个绑定后的函数对象,此时如果错误地认为这个函数的某个属性是 __isabstractmethod__,可能会因为其他逻辑产生混淆(不过实际上绑定后的函数没有这个属性)。

总结一下:正常情况下,只有被 @abstractmethod 装饰的 am 方法的 __isabstractmethod__ 是 True,其他方法要么返回 False,要么没有这个属性。如果你的结果不符合这个预期,优先检查 Python 版本是否过旧。

内容的提问来源于stack exchange,提问作者Toothpick Anemone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:43:22