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

如何让自定义collections.abc.Mapping子类被pickle序列化为dict?

问题描述

我实现了一个继承自collections.abc.Mapping混入接口的自定义外观类MyMapping,代码如下:

from collections import abc
from typing import Mapping

class MyMapping(abc.Mapping):
    def __init__(self, item:Mapping):
        self._item = item        
    def __getitem__(self,key):
        return self._item[key]    
    def __iter__(self):
        return iter(self._item)    
    def __len__(self):
        return len(self._item)

我希望该类被pickle序列化时的结果与直接序列化dict完全一致,即满足:

import pickle

# 期望该语句成立
pickle.dumps(MyMapping({'a':1})) == pickle.dumps({'a':1})

但我不想为了序列化就将所有此类实例手动转换为dict。我尝试过在__reduce__中返回以dict类型为首的元组,但并未生效。是否有其他简便方法?自定义可调用对象或注册分发归约函数的方式显得过于繁琐。

解决方案

你可以通过实现__reduce_ex__方法,让pickle在序列化时直接将MyMapping实例转换成对应的dict对象。__reduce_ex__是__reduce__的扩展版本,优先级更高,能覆盖默认的归约逻辑,适配不同的pickle协议版本。

修改后的代码如下:

from collections import abc
from typing import Mapping
import pickle

class MyMapping(abc.Mapping):
    def __init__(self, item:Mapping):
        self._item = item        
    def __getitem__(self,key):
        return self._item[key]    
    def __iter__(self):
        return iter(self._item)    
    def __len__(self):
        return len(self._item)
    
    def __reduce_ex__(self, protocol):
        # 返回dict类型和对应的参数,让pickle按dict规则序列化
        return (dict, (dict(self),))

测试验证:

obj = MyMapping({'a':1})
print(pickle.dumps(obj) == pickle.dumps({'a':1}))  # 输出 True

为什么之前的__reduce__没生效?

因为abc.Mapping的父类链(如collections.abc.Sized)可能间接影响了pickle的默认处理逻辑,而__reduce_ex__的优先级更高,能确保我们指定的序列化规则被执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:05:47