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

Python自定义数据结构如何实现Pandas式打印与Jupyter可视化?

自定义类实现类似Pandas DataFrame的格式化输出与Jupyter展示

Pandas的实现原理

Pandas的DataFrame并没有在自身类中直接编写__str__的完整实现,而是继承自NDFrame基类。其格式化输出的核心逻辑是:

  • __str__方法会调用内部的to_string()方法,生成对齐后的格式化字符串并返回;
  • __repr__方法会根据输出环境(终端/Jupyter)调整展示内容,全程依赖专用格式化模块处理文本对齐、列宽计算等细节,严格遵循“返回字符串而非直接打印”的Python对象规范。

自定义类的最优实现方案

1. 正确实现__str__与__repr__

禁止在方法内部直接打印内容,必须返回拼接好的格式化字符串。核心是提前计算列名、数据的最大宽度,保证内容对齐。示例代码:

class MyDataFrame:
    def __init__(self, data, index=None):
        self.data = data
        self.index = index if index is not None else range(len(data))
        # 自动生成列名(假设输入为二维列表)
        self.columns = [str(i) for i in range(len(data[0]))] if data else []

    def _get_col_widths(self):
        """计算每列的显示宽度(列名或数据的最大长度 + 2个空格间隔)"""
        widths = []
        # 计算数据列的宽度
        for col in self.columns:
            max_len = len(str(col))
            # 遍历该列所有数据,更新最大长度
            for row in self.data:
                val_len = len(str(row[self.columns.index(col)]))
                if val_len > max_len:
                    max_len = val_len
            widths.append(max_len + 2)
        # 单独计算索引列的宽度
        index_max_len = max(len(str(idx)) for idx in self.index)
        widths.insert(0, index_max_len + 2)
        return widths

    def __str__(self):
        col_widths = self._get_col_widths()
        # 构建表头(含索引列占位)
        header = f"{'':<{col_widths[0]}}"
        for idx, col in enumerate(self.columns):
            header += f"{col:<{col_widths[idx+1]}}"
        # 构建数据行
        data_rows = []
        for idx, row in zip(self.index, self.data):
            row_str = f"{idx:<{col_widths[0]}}"
            for val_idx, val in enumerate(row):
                row_str += f"{val:<{col_widths[val_idx+1]}}"
            data_rows.append(row_str)
        # 拼接并返回最终字符串
        return f"{header.strip()}\n" + "\n".join(data_rows)

    def __repr__(self):
        # 让repr与str输出一致,也可根据需求返回更详细的对象信息
        return self.__str__()

测试使用:

my_df = MyDataFrame([[1, 22, 333], [4444, 55, 6]], index=[10, 20])
print(my_df)

输出效果:

0     1     2
10  1     22    333
20  4444  55    6

2. Jupyter Notebook中的美观展示

Jupyter会调用对象的_repr_html_()方法渲染HTML格式内容,只需在类中实现该方法即可:

def _repr_html_(self):
    # 生成带样式的HTML表格
    html = """
    <style>
        .my-df-table { border-collapse: collapse; margin: 10px 0; }
        .my-df-table th, .my-df-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        .my-df-table th { background-color: #f2f2f2; }
    </style>
    <table class="my-df-table">
        <thead>
            <tr>
                <th>Index</th>
    """
    # 添加列头
    for col in self.columns:
        html += f"<th>{col}</th>"
    html += "</tr></thead><tbody>"
    # 添加数据行
    for idx, row in zip(self.index, self.data):
        html += f"<tr><td>{idx}</td>"
        for val in row:
            html += f"<td>{val}</td>"
        html += "</tr>"
    html += "</tbody></table>"
    return html

在Jupyter中直接输入my_df,就会显示带样式的美观表格。

最佳实践

  • 遵循Python规范:__str__和__repr__必须返回字符串,禁止在方法内直接打印,确保对象能在字符串拼接、日志记录等场景正常使用;
  • 抽离格式化逻辑:将列宽计算、文本拼接等逻辑放到单独的辅助方法(如示例中的_get_col_widths),提升代码可维护性;
  • 适配多场景:__str__做终端友好的简洁输出,__repr__可提供类名、数据规模等详细信息,Jupyter场景通过_repr_html_/_repr_markdown_实现富文本展示;
  • 处理边界情况:为空数据、超长文本等场景做兼容,避免报错或格式混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:52:06