所以我基本上把这个问题提出了一些建议
我有几个类基本上做了一些pandas操作并返回一个数据帧。但是这些数据帧需要对某些滤波器选项进行加法和减法。我打算编写一个类来覆盖 __ add __ 和 __ sub __ 方法,以便我的代码添加或减去这些数据帧,从而实现这些过滤器。以下是基本结构
import ArithOperation
class A:
def dataA(self, filenameA):
dfa = pd.read_excel(filenameA)
return ArithOperation(dfA)
class B:
def dataB(self, filenameB):
dfb = pd.read_excel(filenameB)
return ArithOperation(dfB)
dfA和dfB这里是pandas数据帧。
class ArithOperation:
def __init__(self, df):
self.df = df
def __add__(self, other):
# here the filtering and manual addition is done
return ArithOperation(sumdf)
def __sub__(self, other):
# here the filtering and manual subtraction is done
return ArithOperation(deltadf)
基本上我按以下计算
dfa = A().dataA()
dfb = B().dataB()
sumdf = dfa+dfb
deltadf = dfa-dfb
但是如何使 sumdf 和 deltadf 也具有默认的数据帧功能。我知道我应该将数据帧类继承到 ArithOperation ,但我很困惑并且在很多地方实例化 ArithOperation()时感到有点不舒服。
答案 0 :(得分:0)
在我看来,您希望自定义现有类型的行为(在这种情况下是数据框,但它可以是任何类型)。通常我们想要将某些行为改为另一种行为,或者我们想要扩展该行为,或者我们想要同时执行这两种行为。当我说行为思考方法时。)
您还可以选择has-a方法(即包装对象,通过创建一个新类,其对象包含对原始对象的引用。这样,您可以创建几个新的,不同的或类似的方法来创建新的通过使用存储的引用调用原始方法,最终使用一些现有的东西。这样你就可以将原始的类接口调整到另一个。这就是一个包装模式(或适配器模式)。
这就是你所做的。但是你面临一个问题:你如何接受原始课程的所有可能方法?你将不得不重写所有可能的方法(不是实际的),只是将它们委托给原始类,或者你找到一种方法来委托它们除了你重写的几个。我不会介绍这最后一种可能性,因为你可以随意使用继承,这使得这样的事情非常简单。
只需从原始类继承,您就可以创建与父类具有相同行为的对象。如果您需要新的数据成员,请覆盖__init__
并添加这些成员,但不要忘记调用父类__init__
,否则该对象将无法正确初始化。这就是您使用super().__init__()
的地方,如下所述。如果要添加新方法,只需将常用的def添加到子类中。如果要扩展existant方法,请按照__init__
方法的描述进行操作。如果你想完全覆盖一个方法,只需使用与original.method相同名称的def编写你的版本,它将完全替换原始版本。
因此,在您的情况下,您希望从dataframe类继承,您必须选择是否需要自定义__init__
。如果您需要定义一个,但不要忘记在其中调用父项的原始。然后定义您的自定义方法,例如新的__add__
和__sub__
,替换或扩展原始方法(使用相同的技术)。
小心不要定义您认为是新的方法,但实际上存在于原始类中,因为它们将被覆盖。这是继承的一个小小的不便,特别是如果原始具有许多方法的接口。
使用super()
扩展父类的行为
class A:
pass # has some original __init__
class B(A): # B inherits A
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # preserves parent initialization, passing the same received arguments. If you don't do this parent __init__ will be overrided, not initialising parent object properly.
# add your custom code
pass
super()
的问题在于它解决了在使用多重继承(从多个类继承)时出现的一些问题,在确定应该调用哪个parent方法时,如果你有几个具有相同的命名方法;建议在子类中使用SomeParentClass.method()
调用父方法。
此外,如果您因为需要而对类型进行子类化,那么您不应该害怕在任何地方使用它,如您所说。确保你有充分的理由自定义它(所以想想是否适合数据帧,或者是否有另一种更简单的方法来实现相同的目标而不这样做;不能在这里建议你,我没有大熊猫的经验) ,然后用它代替原来的类。