2017-01-26 21 views
1

上下文:Python:如何實現多態二進制操作。神奇的方法?

我每天都在使用熊貓(處理測量數據),我想了解更多關於Python的知識。

爲此,我正在研究(包裝)類--- MyDataFrame ---將Pandas DataFrame功能與Pint ---一個Python包定義,操作和操作物理量的功能結合起來。

我已經成功地通過__str____get/setitem__和MyDataFrame的底層MySeries(熊貓系列的包裝),一個__truediv__得到一些基本的功能:

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。什麼可能是一個好方法?

我的第一個想法是爲__mul__(self,other)檢查selfother的類型。然而,閱讀關於Python中多態的更多信息(here)讓我想知道其他人如何實現這種多態二元操作。

讓我知道我是否應該給予一些澄清。 PS:作爲旁白。我注意到,在試圖模仿大熊貓的語法我真的寫的包裝,如

def __getitem__(self,key): 
    return self.series[key] 

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

對重定向任何意見,一切如常熊貓方法調用到MyDataFrame/MySeries類的大熊貓一部分?

順便說一句,我得到的順利,這是時候了,我深入到Python的文檔......

回答

0

不幸的是,沒有別的辦法。對於每種類型的熊貓,實施mul已經使用了多態性,因此相應的運算符在第一個參數的類型上表現不同。但是,對於第二個參數,您必須檢查類型。在靜態語言中,這將通過重載基於第二個參數類型的函數完成,但在Python中,您必須使用isinstance。即使是Python標準庫本身也使用這種方法,如果你看看源代碼。

+0

感謝您的解釋。如果無法處理Pint主類的某些困難,則通過'isistance'處理對我來說是好的。 'type(_u(「meter」))''返回pint.unit.build_unit_class。 .Unit'我希望它會返回類似'Unit'的東西。任何線索? – balletpiraat

+1

不要使用'type',它會忽略子類。使用'isinstance(_u(「meter」),Unit)'而不是 –

+0

這已經說明了很多,但是上面的返回'name'Unit'沒有被定義'這使我認爲'import pint'不足以讓Python感知Pint的「單元」類。順便說一句,我正在Jupyter筆記本電腦工作,以防萬一。解決方案是否類似於「品脫進口單位」? – balletpiraat