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

使用slots=True的dataclass调用super()触发TypeError的原因及解决

问题描述

我有一个带类似getter方法的dataclass,无slots时代码可正常运行:

from dataclasses import dataclass

@dataclass()
class A:
    def get_data(self):
        # get some values from object's fields
        # do some calculations
        return "a calculated value"

@dataclass()
class B(A):
    def get_data(self):
        data = super().get_data()
        return data + " (modified)"


b = B()

print(b.get_data())  # a calculated value (modified)

但给dataclass添加slots=True后会触发TypeError:

from dataclasses import dataclass

@dataclass(slots=True)
class A:
    def get_data(self):
        return "a calculated value"

@dataclass(slots=True)
class B(A):
    def get_data(self):
        data = super().get_data()
        return data + " (modified)"


b = B()

print(b.get_data())  # TypeError: super(type, obj): obj must be an instance or subtype of type

改用显式指定类的旧式super(B, self)写法后,错误消失:

from dataclasses import dataclass

@dataclass(slots=True)
class A:
    def get_data(self):
        return "a calculated value"

@dataclass(slots=True)
class B(A):
    def get_data(self):
        data = super(B, self).get_data()
        return data + " (modified)"


b = B()

print(b.get_data())  # a calculated value (modified)
问题原因
  • 使用@dataclass(slots=True)时,Python会生成仅包含指定槽位的类结构,子类默认不会自动继承父类的槽位,这会改变类的内部继承结构。
  • PEP 3135的无参数super()依赖函数定义时绑定的__class__闭包变量,但带slots=True的dataclass子类在生成过程中,会导致这个闭包变量的绑定异常,使得无参数super()无法正确识别当前类与实例的关系,从而抛出类型错误。
  • 显式传递super(B, self)时,直接指定了类和实例,绕过了闭包变量的问题,因此能正常运行。
正确解决方式

有两种可靠的解决办法:

  1. 显式指定super参数:直接使用super(B, self).get_data(),这种写法虽然不符合PEP 3135的简化风格,但在该场景下稳定有效,不存在兼容性问题。
  2. 让子类继承父类槽位:在子类B中显式声明继承父类的槽位,修改后的代码如下:
from dataclasses import dataclass

@dataclass(slots=True)
class A:
    def get_data(self):
        return "a calculated value"

@dataclass(slots=True)
class B(A):
    __slots__ = ()  # 显式继承父类的槽位
    def get_data(self):
        data = super().get_data()
        return data + " (modified)"


b = B()
print(b.get_data())  # a calculated value (modified)

这样无参数super()就能正常工作,因为子类恢复了正常的继承结构,__class__闭包变量可以正确绑定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:05:29