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

Python中继承str的类实例为何被转换为str作为字典键?

为什么Python字典会把自定义str子类实例当成普通字符串处理?

这问题得从字典判断键是否重复的核心逻辑说起,咱们一步步拆解清楚:

字典的键匹配核心规则

字典判断两个对象是否属于同一个键,必须同时满足两个条件:

  1. 两个对象的哈希值(__hash__()返回值)完全相等
  2. 两个对象用==比较时返回True

只要这两个条件都成立,字典就会认定它们是同一个键,后续的赋值操作会直接覆盖原有值,而非新增键值对。

你的SomeClass子类的问题所在

你定义的SomeClass直接继承自str,而且没有重写__hash__和__eq__方法——这意味着它完全复用了str类的哈希计算和相等性判断逻辑:

  • SomeClass('s').__hash__()和普通字符串's'.__hash__()的结果完全一致
  • SomeClass('s') == 's'会返回True(因为str的__eq__只比较字符串内容,不检查对象类型)

所以当你执行some_dict[s] = 40时,字典检测到s(SomeClass实例)和已有的键's'(普通str)满足上述两个条件,就直接把's'对应的值更新为40,而非新增一个键。

为什么键的类型还是str?

字典在存储键时,只会在第一次添加键的时候保存对应的键对象。后续如果用“等效键”(满足哈希相等+==为True)赋值,字典不会替换掉原来的键对象,只是更新对应的值。你的字典里保留的还是最初添加的str类型的's',这就是type(some_dict.keys()[0])返回str的原因。

怎么让自定义类实例成为独立的键?

如果想让SomeClass实例和普通str作为不同的键,你需要重写__eq__和__hash__方法,打破和普通str的等效性:

class SomeClass(str):
    def __eq__(self, other):
        # 仅当other也是SomeClass实例且内容相同时,才判定相等
        return isinstance(other, SomeClass) and super().__eq__(other)
    
    def __hash__(self):
        # 在原str哈希值基础上做修改,确保和普通str哈希不同
        return super().__hash__() ^ 1

some_dict = {'s':42}
s = SomeClass('s')
some_dict[s] = 40
print(some_dict)  # 输出: {'s': 42, 's': 40}
print(type(list(some_dict.keys())[0]))  # <class 'str'>
print(type(list(some_dict.keys())[1]))  # <class '__main__.SomeClass'>

这样就能得到两个独立的键值对了。

内容的提问来源于stack exchange,提问作者Satwik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:33:43