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

为何类上定义的@运算符重载与__getattr__无法直接生效?

问题:为什么类方法定义的__matmul__无法通过@运算符调用?

问题重现

先看第一个示例,直接调用类方法正常,但使用@运算符执行失败:

class Foo:
    @classmethod
    def __matmul__(cls, other):
        return "abc" + other


print(Foo.__matmul__("def"))  # 正常运行,输出"abcdef"
print(Foo @ "def")  # 类型错误:不支持@运算符对'type'和'str'进行操作

__getattr__也存在同样的问题:

class Foo:
    @classmethod
    def __getattr__(cls, item):
        return "abc" + item


print(Foo.__getattr__("xyz")) # 正常运行,输出"abcxyz"
print(Foo.xyz) # 属性错误:类型对象'Foo'没有属性'xyz'

原因解析

Python中,类本身是元类的实例(默认元类是type)。当你对类对象(比如Foo)使用运算符或访问属性时,Python会去查找这个类的元类中定义的特殊方法,而不是类自身的类方法:

  • 直接调用Foo.__matmul__("def")是普通的类方法调用,Python会直接找到Foo类上的这个方法,所以能正常执行。
  • 但使用Foo @ "def"时,Python会去查找Foo的类型(也就是type)的__matmul__方法。默认的type元类没有实现这个方法,因此抛出类型错误。

同理,访问Foo.xyz时,当属性不存在,Python会尝试调用元类的__getattr__方法,而不是Foo类自身的类方法__getattr__,所以会触发属性错误。

解决方案:使用元类

将特殊方法定义在元类上,就能让类对象正常响应运算符或属性查找:

class MetaFoo(type):
    def __matmul__(cls, other):
        return "abc" + other


class Foo(metaclass=MetaFoo):
    pass


print(Foo.__matmul__("def"))  # 正常运行,输出"abcdef"
print(Foo @ "def")  # 正常运行,输出"abcdef"

这是Python的bug吗?

不是,这是Python的设计逻辑:类对象的行为由其元类控制,类自身的类方法仅用于类的直接调用或实例的间接调用,而类对象的特殊方法(运算符重载、属性查找等)需要在元类中定义。

内容的提问来源于stack exchange,提问作者nick maxwell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 14:14:59