如何在非继承pandas.DataFrame的自定义类中模拟其索引功能?
让自定义类具备类似DataFrame的行为(非继承实现)
看起来你已经用代理模式搭好了FalseDF的基础框架,把真实的DataFrame作为内部属性,还实现了__getitem__来支持索引取值。想要让这个类更贴近DataFrame的使用体验,可以试试下面这些方法:
1. 逐个代理常用方法
如果只需要支持几个特定的DataFrame方法,比如head()、describe(),可以直接在类里定义对应的方法,内部调用self.df的方法即可:
import pandas import numpy class FalseDF(object): def __init__(self, df): self.df = df def __getitem__(self, item): return self.df.__getitem__(item) # 代理head方法,保留默认参数 def head(self, n=5): return self.df.head(n) # 代理统计描述方法 def describe(self): return self.df.describe() # 测试一下 df = pandas.DataFrame(numpy.reshape(numpy.arange(10), (2, 5))) fdf = FalseDF(df) print(fdf.head()) print(fdf.describe())
2. 动态代理所有属性和方法(更省心)
要是不想一个个写代理方法,用__getattr__魔法方法就能实现“自动转发”——当访问FalseDF实例没有的属性或方法时,会自动去内部的self.df里找:
class FalseDF(object): def __init__(self, df): self.df = df def __getitem__(self, item): return self.df.__getitem__(item) # 动态代理所有未定义的属性/方法 def __getattr__(self, name): return getattr(self.df, name) # 现在可以直接用DataFrame的任意属性和方法了 print(fdf.shape) # 输出 (2, 5) print(fdf.mean()) # 输出各列均值 fdf.plot() # 直接调用绘图方法
3. 支持赋值操作
想要实现fdf['new_col'] = [1,2]这种DataFrame式的赋值,只需要实现__setitem__方法:
class FalseDF(object): def __init__(self, df): self.df = df def __getitem__(self, item): return self.df.__getitem__(item) def __setitem__(self, key, value): self.df.__setitem__(key, value) def __getattr__(self, name): return getattr(self.df, name) # 测试赋值 fdf['new_col'] = [10, 20] print(fdf['new_col'])
4. 让打印输出更像DataFrame
默认情况下print(fdf)会输出类的内存地址,想要和print(df)一样显示表格格式,实现__repr__和__str__方法就行:
class FalseDF(object): def __init__(self, df): self.df = df def __getitem__(self, item): return self.df.__getitem__(item) def __setitem__(self, key, value): self.df.__setitem__(key, value) def __getattr__(self, name): return getattr(self.df, name) # 自定义打印格式 def __repr__(self): return self.df.__repr__() def __str__(self): return self.df.__str__() # 现在打印fdf就和打印df完全一样了 print(fdf)
这种通过包装对象实现功能复用的方式叫做代理模式,相比直接继承DataFrame,它能让你更灵活地控制对外暴露的功能,还能避免继承带来的冗余属性和方法。
内容的提问来源于stack exchange,提问作者CiaranWelsh
相关产品推荐
相关产品推荐

