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

如何实现支持具名键的类字典结构?能否修改__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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:46:16