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

使用点符号访问MyClass.my_attribute时调用何方法?如何实现访问提示?

问题解答

为啥之前的代码没效果?

你写的__getattr__和__getattribute__是实例专属方法,只有访问类的实例对象属性时才会触发。但你是直接访问类本身的属性,类其实是元类(默认是type)的实例,这时候只会调用元类的属性访问逻辑,跟你在类里定义的那俩方法没关系。

访问类属性时到底调用啥方法?

直接访问MyClass.my_attribute这类类属性时,会调用该类元类的__getattribute__方法(默认元类是type,所以调用的是type.__getattribute__)。要是访问的属性不存在,才会触发元类的__getattr__(不过默认type没实现这个方法,所以直接报错)。

实现需求的两种实用方法

方法1:自定义元类(通用型)

自己写个元类,重写它的__getattribute__方法,就能在访问任何类属性时添加打印逻辑:

class MyMeta(type):
    def __getattribute__(cls, name):
        # 跳过特殊属性(比如__class__、__name__),防止无限递归
        if not name.startswith('__'):
            print(f"getting {name} attr")
        return super().__getattribute__(name)

class MyClass(metaclass=MyMeta):
    my_attribute = "abc"

print(MyClass.my_attribute)

运行输出:

getting my_attribute attr
abc

方法2:类装饰器(针对特定属性)

如果只需要给部分类属性加提示,用类装饰器结合property也能实现:

def track_class_attrs(cls):
    # 遍历类里的非特殊属性
    for attr_name, attr_val in list(cls.__dict__.items()):
        if not attr_name.startswith('__'):
            # 包装属性获取逻辑
            def wrapper(name=attr_name):
                print(f"getting {name} attr")
                return cls.__dict__[name]
            # 把原属性换成property
            setattr(cls, attr_name, property(wrapper))
    return cls

@track_class_attrs
class MyClass:
    my_attribute = "abc"

print(MyClass.my_attribute)

运行输出:

getting my_attribute attr
abc

注意:方法2里用了property,之后要是修改类属性的值,得重新设置property才会继续触发打印;而元类的方法更灵活,哪怕后续动态添加类属性也能生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 12:35:14