Python:如何实现多态二进制操作。神奇的方法?

时间:2017-01-26 12:06:09

标签: python pandas polymorphism pint

上下文:

我每天都使用Pandas(处理测量数据),我想了解更多有关Python的信息。

为此,我正在开发一个(包装)类 - MyDataFrame ---它将Pandas DataFrame功能与Pint的功能结合起来 - 一个用于定义,操作和操作物理的Python包量。

我已经设法通过__str____get/setitem____truediv__为MyDataFrame的底层MySeries(Pandas系列包装器)获取了一些基本功能:

API示例:

import pint
_u = pint.UnitRegistry()

_u("meter")
>>> 1 meter

type(_u("meter"))
>>> pint.unit.build_quantity_class.<locals>.Quantity

data = [[0,1,2,3],[4,5,6,7]]

df = pd.DataFrame(data,columns=["time","distance"])

units = {"distance":_u("meter"), "time":_u("second")}

mdf = MyDataFrame(df, units)

mdf["speed"] = mdf["distance"]/mdf["time"]

mdf["speed"].unit == _u("meter per second")
>>> True

到目前为止,我一直将实施保持在最低限度,例如:

class MyDataFrame:
"""df: pandas DataFrame, units: dict of str - Pint quantity key-value pairs."""
    def __init__(self,df,units):

        error_handling(df,units)

        self.df = df
        self.units = units

    def __getitem__(self,key):
        if key in units.keys():
            return MySeries(self.df[key],self.units[key]) 

class MySeries:
"""series: pandas Series, units: a Pint quantity value."""
    def __init__(self,series,unit):
        self.series = series
        self.unit = unit

    def __truediv__(self,other):
        return MySeries(self.series/other.series,self.unit/other.unit)

问题:

但现在我想扩展这个基本概念,以便我们可以做到这一点。

mdf["speed"] * 60*_u(second)

换句话说,使MySeries __mul__()多态 - 不仅可以将MySeries与MySeries相乘,还可以将MySeries与Pint Quantities相乘(反之亦然)。什么是一个好方法?

我的第一个想法是__mul__(self,other)检查selfother的类型。但是,阅读更多有关Python(here)中的多态性的信息让我想知道其他人如何实现这种多态二进制操作。

如果我应该澄清一下,请告诉我。

PS:暂且不说了。我注意到,在尝试模仿Pandas语法时,我正在编写诸如

之类的包装器
def __getitem__(self,key):
    return self.series[key]

def notnull(self):
    return self.series.notnull()

有关将所有常规Pandas方法调用重定向到MyDataFrame / MySeries类的Pandas部分的任何建议吗?

顺便说一句,我得知我现在是时候深入研究Python的文档......

1 个答案:

答案 0 :(得分:0)

不幸的是,没有其他办法。多态性已经被用于为每种类型的Pandas实现mul,因此相应的运算符在第一个参数的类型上表现不同。但是,对于第二个参数,您必须检查类型。在静态语言中,这可以通过基于第二个参数类型重载函数来完成,但在Python中,您必须使用isinstance。如果你看一下源代码,即使Python标准库本身也会使用这种方法。