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

自定义__dict__方法触发mypy类型错误?代码问题解析

错误原因与问题分析

1. mypy错误原因

__dict__是Python中object类的只读属性,类型为dict[str, Any],用于存储实例的属性键值对。你将它定义成了方法,这就和父类的属性签名完全不兼容——mypy会严格检查子类对父类成员的重写是否符合类型规范,因此触发"Signature of "dict" incompatible with supertype "object""错误。

2. 运行不符合预期的原因

JSON序列化(比如json.dumps())在处理对象时,会尝试读取对象的__dict__属性来获取可序列化的字段。但你把__dict__改成了方法,序列化时要么拿到的是方法对象(无法序列化),要么你在方法里返回了错误的结构,导致结果不符合预期。


修复方案

不要重载__dict__属性,改用以下几种标准方式实现自定义JSON序列化:

方案1:使用__getstate__方法

Python的json模块在序列化对象时,会优先调用__getstate__方法获取对象的可序列化状态,返回的字典会被直接用于序列化。

方案2:自定义__json__方法 + 自定义编码器

如果需要更明确的序列化逻辑,可以自定义__json__方法,再配合JSONEncoder子类来自动调用它。

方案3:使用dataclasses模块(推荐)

如果你的类是数据类,使用dataclasses.asdict()可以直接将实例转为字典,无需手动处理。


代码示例

错误代码示例

import json

class RepeatedValue:
    def __init__(self, value: int, count: int):
        self.value = value
        self.count = count

    # 错误:把__dict__定义成了方法
    def __dict__(self) -> dict[str, int]:
        return {"value": self.value, "total": self.value * self.count}

# 运行时问题:json.dumps会尝试读取__dict__属性,而非调用方法
rv = RepeatedValue(5, 3)
print(json.dumps(rv))  # 运行报错或结果不符合预期
# mypy检查会触发Signature错误

修复方案1:使用__getstate__

import json

class RepeatedValue:
    def __init__(self, value: int, count: int):
        self.value = value
        self.count = count

    def __getstate__(self) -> dict[str, int]:
        return {"value": self.value, "total": self.value * self.count}

rv = RepeatedValue(5, 3)
print(json.dumps(rv))  # 输出: {"value": 5, "total": 15}
# mypy检查无错误

修复方案2:自定义编码器 + __json__

import json

class RepeatedValue:
    def __init__(self, value: int, count: int):
        self.value = value
        self.count = count

    def __json__(self) -> dict[str, int]:
        return {"value": self.value, "total": self.value * self.count}

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, '__json__'):
            return obj.__json__()
        return super().default(obj)

rv = RepeatedValue(5, 3)
print(json.dumps(rv, cls=CustomEncoder))  # 输出: {"value": 5, "total": 15}

修复方案3:使用dataclasses

import json
from dataclasses import dataclass, asdict

@dataclass
class RepeatedValue:
    value: int
    count: int

    # 自定义序列化逻辑
    def to_dict(self) -> dict[str, int]:
        base = asdict(self)
        base["total"] = self.value * self.count
        return base

rv = RepeatedValue(5, 3)
print(json.dumps(rv.to_dict()))  # 输出: {"value": 5, "count": 3, "total": 15}

内容的提问来源于stack exchange,提问作者Joaquín Ruiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:57:31