gpt4 book ai didi

python - 扩展现有 3rd 方库的现有类的功能的最佳方法是什么?

转载 作者:太空宇宙 更新时间:2023-11-04 05:14:23 24 4
gpt4 key购买 nike

例如,我在代码中使用了很多 pandas.DataFrames。这是一个非常大的类,有很多部分,它有一个非常类似于功能的 API,您倾向于将它的方法调用链接在一起。

如果能够轻松地向这个现有类添加功能,同时仍然保持功能性、流畅的 API 完好无损,感觉会很好。

我想把这个类变成一些特定于领域的东西,以便删除很多在使用这个类时经常使用的特定于领域的样板代码。

假设我在梦中能够做这样的事情:

pandas.read_csv('sales.csv') \
.filter(items=['one', 'three']) \
.apply(myTransformationFunction) \
.saveToHivePartition(tablename = 'sales', partitionColumn = 'four') \
.join(pandas.read_csv('employees.csv')) \
.filter(items=['one','three','five']) \
.saveToHivePartition(tablename = 'EmployeeMetrics', partitionColumn = 'ten')

在此示例中,saveToHivePartition 是一个自定义方法,它执行大量操作以原子方式将某些内容保存到 HDFS 的正确位置,然后将该信息添加到 hive 元数据存储区。 super 有用!

显然,“简单”的答案是简单地创建一个独立的函数,我可以将 DataFrame 对象连同我需要的其他参数一起传递给该函数。每次我想执行保存时,我都需要将数据帧封装到一个变量中,然后将该变量传递到一个单独的函数中。远没有上面的例子那么干净!

接下来想到的是创建一些很酷的新 SuperDataFrame 类,它是 DataFrame 的超集。这种方法的唯一问题是:你如何构建它?我无法更改 pandas.read_csv() 以开始返回我的新类(class)。我无法将基类转换为子类。我可以让 SuperDataFrame 成为...数据框类的包装器吗?但后来我想,任何时候我想调用一个基本的 DataFrame 函数,它都必须是这样的:

SuperDataFrame(pandas.read_csv('sales.csv')) \
.df.filter .... \
.df.apply .... \
.saveToHivePartition .... \
.df.join .... \
.df.filter .... \
.saveToHivepartition ....

我什至认为这行不通,因为这假设每当 pandas 执行一个功能时,它都会就地改变 DataFrame,我敢肯定它甚至不会这样做。

有什么想法吗?或者这只是一件坏事?

最佳答案

您可以使用 constructor-override properties确保 pandas 操作返回新类的实例。一个简单的例子:

class MyDF(pandas.DataFrame):
@property
def _constructor(self):
return MyDF

def myMethod(self):
return "I am cool"

>>> d = MyDF([[1, 2, 3], [4, 5, 6], [7, 8, 9]], columns=["A", "B", "C"])
>>> d.filter(["A", "B"]).apply(lambda c: c**2).myMethod()
'I am cool'

当然,您还必须创建自己的 Series 子类并可能定义 custom data slots如果您还希望能够处理系列。

也就是说,我不清楚您的示例是否真的证明了这一点。您已经可以在普通 DataFrames 上链接方法调用,所以如果您只想保存一些中间阶段,那么做起来并不麻烦:

data = pandas.read_csv('sales.csv') \
.filter(items=['one', 'three', 'five']) \
.apply(myTransformationFunction)

data2 = data.join(pandas.read_csv('employees.csv')) \
.filter(items=['one', 'three'])

saveToHivePartition(data, tablename='sales', partitionColumn='four')
saveToHivePartition(data2, tablename='EmployeeMetrics', partitionColumn='ten')

(由于我在对问题的评论中提到的问题,我更改了过滤器的顺序。先过滤到较小的子集,然后再过滤到较大的子集是没有意义的;较大的子集不会稍后会有,因为其中一些已经被过滤掉了。)

将事物编写为方法链的能力本身并不是一种优势。我特别怀疑像您的 .saveToHivePartition 这样的链接方法,它们可能只是因为它们的副作用而被调用。当它们以流水线方式运行时,链接方法是有意义的,每个方法都接受前一个的输入并修改它以传递给下一个。但是,只产生副作用并返回未更改对象的方法并不能使代码更具可读性。

另请注意,此解决方案特定于 pandas。通常,如果某些库中的类创建彼此的实例,则必须仔细设计库以允许以保留类之间关系的方式进行子类化。 Pandas 已使用我描述的构造函数覆盖机制完成此操作,但它并不总是那样,在此之前,很难做你想做的事情。

关于python - 扩展现有 3rd 方库的现有类的功能的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42145664/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com