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

子类化pd.DataFrame查看数据时触发‘object has no attribute '_data'’错误

这个问题我之前也碰到过!核心原因是你用super().__new__(cls, df)创建实例时,只完成了对象的实例化,但没有触发pandas.DataFrame的初始化逻辑——也就是__init__方法没被调用,导致DataFrame内部的核心属性(比如_data)都没被初始化,所以查看实例时会抛出AttributeError。

修正类方法,正确初始化实例

你不需要直接调用__new__,而是通过cls(df)来创建TestFrame实例,这样会自动调用父类的__init__,完成所有内部属性的初始化,之后再添加自定义属性就没问题了:

import pandas as pd
data = pd.DataFrame({'A': [1, 2], 'B': [2, 3], 'C': [4, 5]})

class TestFrame(pd.DataFrame):
    _metadata = pd.DataFrame._metadata + ["addnl"]
    
    @property
    def _constructor(self):
        return TestFrame
    
    @property
    def _constructor_sliced(self):
        return pd.Series
    
    @classmethod
    def plus_one(cls, df):
        # 用cls()创建实例,触发完整的初始化流程
        tf = cls(df)
        tf.addnl = 1
        return tf

t1 = TestFrame.plus_one(data)
print(t1)
# 输出:
#    A  B  C
# 0  1  2  4
# 1  2  3  5
print(t1.addnl)  # 输出: 1

为什么之前的写法不行?

super().__new__(cls, df)只是调用了object.__new__创建了一个空的TestFrame对象,但没有执行DataFrame的初始化逻辑——DataFrame的__init__方法会处理传入的数据,初始化_data、_axes等核心内部属性,这些都是后续操作(比如打印、切片)必须的。你手动调用__new__跳过了这一步,自然会报错。

进阶:自定义__init__方法(如果需要)

如果你想在初始化时直接传入自定义属性,也可以重载__init__,但必须确保调用父类的__init__:

class TestFrame(pd.DataFrame):
    _metadata = pd.DataFrame._metadata + ["addnl"]
    
    @property
    def _constructor(self):
        return TestFrame
    
    @property
    def _constructor_sliced(self):
        return pd.Series
    
    def __init__(self, *args, addnl=None, **kwargs):
        # 先调用父类的初始化方法
        super().__init__(*args, **kwargs)
        # 再设置自定义属性
        self.addnl = addnl
    
    @classmethod
    def plus_one(cls, df):
        # 直接通过构造器传入addnl参数
        return cls(df, addnl=1)

这样写的好处是更符合面向对象的设计,而且_metadata里的addnl会确保在你对TestFrame做操作(比如切片、过滤)返回新实例时,这个属性会被自动保留。比如:

t2 = t1[t1['A'] > 1]
print(t2.addnl)  # 输出: 1,属性被保留了

内容的提问来源于stack exchange,提问作者Chris J Harris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:27:47