如何为pandas.DataFrame派生类添加新属性?解决递归报错问题
解决pandas DataFrame派生类添加属性的递归错误问题
当你直接在__init__中调用super().__init__前设置self.derived时,会触发pandas重写的__setattr__方法。pandas的__setattr__会对属性进行特殊处理,过程中可能间接调用到初始化相关逻辑,导致无限递归,最终抛出RecursionError。
以下是几种正确的解决方式:
方案一:使用object.__setattr__绕过pandas的属性处理
在调用父类初始化前,用Python原生的object.__setattr__来设置自定义属性,避免触发pandas的__setattr__逻辑:
from pandas import DataFrame class DataFrameDerived(DataFrame): def __init__(self, *args, **kwargs): object.__setattr__(self, 'derived', True) super().__init__(*args, **kwargs) df = DataFrameDerived({'a':[1,2,3]}) print(df.derived) # 输出 True
方案二:先调用父类初始化,再设置属性
如果不需要在父类初始化前设置属性,可以先完成DataFrame的初始化,再赋值自定义属性:
from pandas import DataFrame class DataFrameDerived(DataFrame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.derived = True df = DataFrameDerived({'a':[1,2,3]}) print(df.derived) # 输出 True
进阶:确保方法返回实例时保留自定义属性
如果你的子类需要支持pandas方法(比如过滤、筛选)返回的实例也保留自定义属性,需要重写__finalize__方法——这是pandas用于同步实例元数据的钩子:
from pandas import DataFrame class DataFrameDerived(DataFrame): def __init__(self, *args, **kwargs): # 可以通过kwargs传入自定义属性值,更灵活 self.derived = kwargs.pop('derived', True) super().__init__(*args, **kwargs) def __finalize__(self, other, method=None, **kwargs): # 先调用父类的finalize逻辑 super().__finalize__(other, method=method, **kwargs) # 如果源实例是子类类型,同步自定义属性 if isinstance(other, DataFrameDerived): self.derived = other.derived return self # 测试:过滤后返回的实例仍保留属性 df = DataFrameDerived({'a':[1,2,3]}) filtered_df = df[df['a'] > 1] print(filtered_df.derived) # 输出 True
内容的提问来源于stack exchange,提问作者Antonio Amador
相关产品推荐
相关产品推荐

