如何实现支持具名键的类字典结构?能否修改__set__/__get__接收关键字参数?
问题翻译
我需要一种极简的类字典结构,要求支持具名键。比如我有一个值f(k, q),原本可以用嵌套字典实现,比如f[0][1] = 'value'或者f[(0,1)] = 'value',但用户很容易搞混f[0][1]和f[1][0]的顺序。所以我想要类似f[k=0, q=0] = 'value'的写法。如果用自定义类实现f.get()和f.set(value)这类方法,代码可读性会大打折扣——因为这些表达式会嵌入复杂公式里,可读性至关重要,所以赋值必须通过=运算符完成,不能把值当成函数参数传递。请问能不能修改__set__和__get__魔法方法来接受关键字参数?
解决方案
首先要明确:你提到的__get__和__set__是描述符协议的方法,和字典取值赋值相关的是__getitem__与__setitem__。这两个方法本身不直接支持关键字参数,但可以利用Python 3.10+的语法特性——方括号内允许传入关键字参数,这些参数会被自动打包成字典,我们可以在自定义类里处理这个字典来实现需求。
基础实现
class NamedDict: def __init__(self): self._data = {} def __getitem__(self, kwargs): # 将关键字参数字典转为排序后的键值对元组,确保键的唯一性 key = tuple(sorted(kwargs.items())) return self._data[key] def __setitem__(self, kwargs, value): key = tuple(sorted(kwargs.items())) self._data[key] = value
使用示例
f = NamedDict() # 赋值 f[k=0, q=0] = 'foo' f[q=1, k=0] = 'bar' # 内部按键排序,这和f[k=0, q=1]是同一个键 # 取值 print(f[k=0, q=0]) # 输出 'foo' print(f[q=0, k=0]) # 同样输出 'foo'
进阶:限制键名
如果需要严格限定只能使用指定的键(比如只允许k和q),可以在方法里添加校验逻辑:
class RestrictedNamedDict: def __init__(self): self._data = {} self._allowed_keys = {'k', 'q'} def __getitem__(self, kwargs): if kwargs.keys() != self._allowed_keys: raise ValueError(f"仅支持关键字参数:{self._allowed_keys}") key = tuple(sorted(kwargs.items())) return self._data[key] def __setitem__(self, kwargs, value): if kwargs.keys() != self._allowed_keys: raise ValueError(f"仅支持关键字参数:{self._allowed_keys}") key = tuple(sorted(kwargs.items())) self._data[key] = value
注意事项
- 该写法依赖Python 3.10及以上版本,因为方括号内使用关键字参数是3.10引入的新语法。
- 内部用排序后的元组作为键,是为了避免因关键字参数顺序不同导致的键冲突(比如
f[k=0, q=0]和f[q=0, k=0]会被识别为同一个键)。
内容的提问来源于stack exchange,提问作者Somebody Young
相关产品推荐
相关产品推荐

