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

Python __repr__返回字符串但实例类型不为str问题排查

问题说明

尝试使用__repr__特殊方法让自定义类实例输出为字符串形式,虽然交互环境下的输出看起来是字符串,但通过type()检测实例类型时,结果并非字符串类型,实际运行结果如下:

>>> ColumnSet.COL_A
Out: "COL_A"
>>> type(ColumnSet.COL_A)
Out: __main__.Column
>>> type(ColumnSet.COL_A) == str
Out: False

期望实现的运行效果:

>>> ColumnSet.COL_A
Out: "COL_A"
>>> type(ColumnSet.COL_A)
Out: str
>>> type(ColumnSet.COL_A) == str
Out: True 

尝试在__repr__方法内部将返回值显式转换为字符串,无法解决问题。核心诉求是:既可以得到简洁的字符串展示效果,又能保留实例的属性访问能力,比如正常调用ColumnSet.COL_A.data_type这类属性。
当前实现代码:

from dataclasses import dataclass


@dataclass
class Column:
    column_name: str
    data_type: str
    description: str

    def __repr__(self) -> str:
        return str(self.column_name)


@dataclass
class ColumnSet:
  COL_A = Column(
      **{
          "column_name": "COL_A",
          "data_type": "bool",
          "description": "Lorem Ipsum",
      }
  )
  COL_B = Column(
      **{
          "column_name": "COL_B",
          "data_type": "bool",
          "description": "Lorem Ipsum",
      }
  )
原因分析

你对__repr__的作用存在误解:这个方法只负责定义实例被打印、在REPL环境输出时的展示文本,完全不会修改实例本身的类型。Column类实例化出的对象永远是Column类型,不可能因为__repr__返回字符串就变成原生str类型。
另外你提出的两个核心诉求存在本质冲突:

  • 如果ColumnSet.COL_A真的是原生str类型(即type(ColumnSet.COL_A) is str返回True),就不可能挂载.data_type这类自定义属性,Python原生str类型不支持动态添加自定义字段
  • 只要实例能访问自定义属性,它就不可能是原生str类型,type()检测必然返回对应的自定义类类型

你在交互环境看到的"COL_A"输出,只是REPL调用__repr__后打印的结果,不代表变量本身变成了字符串。

可行方案

方案1:继承str实现自定义列类型(最接近预期效果)

通过继承str创建自定义子类,可以让实例在绝大多数场景下和原生字符串行为完全一致,同时支持挂载自定义属性,满足属性访问需求:

class Column(str):
    def __new__(cls, column_name: str, data_type: str, description: str):
        # 构造字符串实例时,用列名作为字符串本身的值
        return super().__new__(cls, column_name)
    
    def __init__(self, column_name: str, data_type: str, description: str):
        self.column_name = column_name
        self.data_type = data_type
        self.description = description


class ColumnSet:
  COL_A = Column(
      column_name="COL_A",
      data_type="bool",
      description="Lorem Ipsum",
  )
  COL_B = Column(
      column_name="COL_B",
      data_type="bool",
      description="Lorem Ipsum",
  )

运行效果:

>>> ColumnSet.COL_A
'COL_A'
>>> # 所有字符串场景可直接使用
>>> isinstance(ColumnSet.COL_A, str)
True
>>> f"选择列:{ColumnSet.COL_A}"
'选择列:COL_A'
>>> # 自定义属性可正常访问
>>> ColumnSet.COL_A.data_type
'bool'

注意:该方案下type(ColumnSet.COL_A)会返回<class '__main__.Column'>,无法满足type(x) == str的判断——这是Python类型系统的限制,只要是带自定义属性的字符串对象,必然是str子类的实例,不可能是原生str。实际开发中类型判断应该优先用isinstance(),直接用type()做相等判断本身就是不符合Python编码规范的写法。

方案2:保留原有实现,仅优化展示

如果没有强需求要通过type() == str的判断,你原来的__repr__写法已经完全满足需求:实例可以正常访问所有自定义属性,输出时自动展示为简洁的列名,不需要做额外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:24:29