Getattr 和 getattribute 的本质区别是什么?
这两个名字长得像,本质差别还挺大的。
先把关系说清楚:getattribute 是属性访问的“正门”,所有访问都必须经过它;getattr 是“后门”,只有当正门找不到属性时才会打开。
下面我拆开来说👇
🔑 本质区别一句话¶
-
getattribute:无条件拦截。访问任何属性(不管存在与否)都会先调用它。 -
getattr:有条件兜底。只有在常规查找(包括getattribute)都失败、抛出AttributeError时才会被调用。
⚡ 调用顺序:一个清晰的流程图¶

🧪 示例对比¶
class Demo:
def __init__(self):
self.exist = "我是存在的属性"
def __getattribute__(self, name):
print(f"__getattribute__ 被调用:{name}")
return super().__getattribute__(name) # 必须走父类,否则递归
def __getattr__(self, name):
print(f"__getattr__ 被调用:{name}")
return f"动态生成的 {name}"
obj = Demo()
print(obj.exist) # 输出 __getattribute__ 被调用:exist → 返回 "我是存在的属性"
print(obj.miss) # 输出 __getattribute__ 被调用:miss → 失败 → __getattr__ 被调用:miss → 返回 "动态生成的 miss"
可以看到:
-
getattribute无论属性存不存在,都会被调用。 -
getattr只在miss这种缺失属性时才出面。
⚠️ 容易踩的坑¶
🧠 总结¶
-
getattribute= 霸道总裁:所有属性访问都要先经我手。 -
getattr= 救火队长:只有当常规查找失败时才出场善后。
在需要动态属性(如 ORM 的惰性加载)时,我们优先用 getattr;只有在要完全控制属性访问(如代理对象、RPC 客户端)时,才考虑谨慎重写 getattribute。
这样就把两个方法的“管辖范围”和调用时机讲清楚了,有什么细节需要再展开的我们随时聊。