为何自定义字典赋值给函数__dict__后,f.k2无法解析而f.k1可以?
为什么f.k1能访问但f.k2不行?
这个问题的核心在于Python函数对象的属性查找机制和你自定义字典子类的行为不匹配,我来给你拆解清楚:
先看你的代码逻辑
你自定义了MyDict子类,只重写了__getitem__方法——当键是'k2'时返回'v2',其他情况沿用父类dict的逻辑。然后你把函数f的__dict__替换成了这个MyDict的实例(初始化时传入了{'k1': 'v1'})。
为什么f.k1正常?
当你访问f.k1时:
- Python首先检查
'k1'是不是f.__dict__里的键(因为'k1'确实在初始化的字典里,'k1' in f.__dict__返回True) - 确认键存在后,Python会调用
f.__dict__['k1']来获取值,这时候触发你重写的__getitem__,顺利返回'v1'
为什么f.k2报错?
而访问f.k2时,问题出在属性查找的第一步:
- Python会先检查
'k2'是否存在于f.__dict__的键集合中。但你没有重写MyDict的__contains__方法,这个方法继承自父类dict,而'k2'并不是这个字典的实际键,所以'k2' in f.__dict__返回False - 函数对象的属性查找逻辑是:只有当属性名存在于
__dict__的键里时,才会去调用__getitem__取值;如果键不存在,直接抛出AttributeError,根本不会走到你重写的__getitem__那一步
怎么解决?
如果想让f.k2能正常访问,你需要同时重写MyDict的__contains__方法,让它在检查'k2'时返回True:
class MyDict(dict): def __getitem__(self, item): if item == 'k2': return 'v2' return super().__getitem__(item) def __contains__(self, item): if item == 'k2': return True return super().__contains__(item)
修改后再测试,f.k2就能返回'v2'了。
另外补充个小细节:直接调用f.__dict__['k2']是能拿到'v2'的,因为这会直接触发__getitem__;但.属性访问是走完整的属性查找流程,两者的逻辑不一样哦。
内容的提问来源于stack exchange,提问作者wim
相关产品推荐
相关产品推荐

