自定义Python字典中self[key]=value未调用__setitem__方法的原因
问题原因解析
核心原因:下标赋值与实例方法绑定的差异
Python的下标赋值语法self[key] = value,本质是调用类定义中的__setitem__方法,而非你通过self.__setitem__ = xxx绑定在实例上的方法。
你在__init__里的操作是给实例对象本身绑定了__setitem__属性(要么是父类方法,要么是自定义的__setitemmaxlen__),但这种实例级别的方法覆盖,不会影响Python内置语法(如下标赋值)对方法的查找——内置语法会直接从类的MRO链中找__setitem__,完全不会读取实例的属性字典。
而当你直接调用self.__setitem__(key, value)时,是明确访问实例上的__setitem__属性,也就是你在__init__里绑定的自定义方法,所以长度限制逻辑会正常生效。
代码优化建议
你当前通过动态绑定实例__setitem__的方式不符合Python类设计的常规规范,容易引发语法与方法绑定的冲突。更稳妥的方式是在类的__setitem__方法内部做分支判断:
from collections import OrderedDict from weakref import proxy class AttachedAutoLimitedDict(OrderedDict): """一种专用于关联对象的特殊字典实现: - 当请求不存在的键时,会调用关联对象的生成方法自动生成对应值 - 支持设置最大长度,超出时按FIFO规则移除旧键值对""" def __init__(self, associated_object, max_len: int | None = None, *args, **kwargs): super().__init__(*args, **kwargs) self.associated_object = proxy(associated_object) self.max_len = max_len def __missing__(self, key): """重写__missing__方法:当键不存在时,调用关联对象的生成方法生成值""" try: self[key] = self.associated_object.generation_method(key) return self[key] except AttributeError: super().__missing__(key) def __setitem__(self, key, value): """实现长度限制逻辑,超出最大长度时按FIFO移除最老元素""" if self.max_len is not None and len(self) >= self.max_len: self.popitem(last=False) super().__setitem__(key, value)
这个版本直接在类的__setitem__里判断max_len是否存在,不管是下标赋值还是直接调用self.__setitem__,都会走同一个逻辑,彻底避免了实例方法绑定带来的问题。
内容的提问来源于stack exchange,提问作者chriss
相关产品推荐
相关产品推荐

