【问题标题】:Proper way to extend Python class扩展Python类的正确方法
【发布时间】:2018-06-29 19:13:02
【问题描述】:

我希望扩展 Panda 的 DataFrame,创建一个对象,其中所有原始 DataFrame 属性/方法都完好无损,同时提供一些新的属性/方法。我还需要能够将已经是 DataFrame 的对象转换(或复制)到我的新类。我所拥有的似乎有效,但我觉得我可能违反了一些基本惯例。这是这样做的正确方法,还是我应该首先这样做?

import pandas as pd

class DataFrame(pd.DataFrame):
    def __init__(self, df):
        df.__class__ = DataFrame # effectively 'cast' Pandas DataFrame as my own

我的想法是我可以直接从 Pandas DataFrame 初始化它,例如:

df = DataFrame(pd.read_csv(path))

【问题讨论】:

  • 你混淆了继承和组合。你的DataFrame 类既“有”又“是”pd.DataFrame
  • self = df 什么都不做

标签: python pandas class inheritance


【解决方案1】:

如果我不得不这样做,我可能会这样做:

import pandas as pd

class CustomDataFrame(pd.DataFrame):
    @classmethod
    def convert_dataframe(cls, df):
        df.__class__ = cls
        return df

    def foo(self):
        return "Works"


df = pd.DataFrame([1,2,3])
print(df)
#print(df.foo())    # Will throw, since .foo() is not defined on pd.DataFrame

cdf = CustomDataFrame.convert_dataframe(df)
print(cdf)
print(cdf.foo())    # "Works"

注意:这将永远改变您传递给 convert_dataframe 的 df 对象:

print(type(df))     # <class '__main__.CustomDataFrame'>
print(type(cdf))    # <class '__main__.CustomDataFrame'>

如果你不想这样,你可以在类方法中复制数据框。

【讨论】:

    【解决方案2】:

    如果您只想在运行其他任何内容之前将方法添加到 DataFrame 只是猴子补丁,如下所示。

    >>> import pandas                                
    >>> def foo(self, x):                            
    ...     return x                                 
    ...                                              
    >>> foo                                          
    <function foo at 0x00000000009FCC80>             
    >>> pandas.DataFrame.foo = foo                   
    >>> bar = pandas.DataFrame()                     
    >>> bar                                          
    Empty DataFrame                                  
    Columns: []                                      
    Index: []                                        
    >>> bar.foo(5)                                   
    5                                                
    >>>
    

    【讨论】:

    • 感谢您的回复,我实际上想在数据框中添加一些专门与方法交互的属性,我已经更新了问题
    • 您可以创建一个初始化方法(不称为__init__),在创建后将新属性修补到数据框上
    【解决方案3】:
    if __name__ == '__main__':
        app = DataFrame()
        app()
    

    事件

    super(DataFrame,self).__init__()
    

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 2012-05-28
      • 1970-01-01
      • 2023-04-01
      • 2018-09-24
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多