2017-01-26 3 views
1

Контекст:Python: Как реализовать полиморфный двоичный код op. магические методы?

Я использую Pandas на ежедневной основе (обработка данных измерений), и я хотел бы узнать больше о Python.

Для этого я работаю над классом (оболочкой) --- MyDataFrame ---, который сочетает функциональность Pandas DataFrame с параметром Pint --- пакет Python для определения, управления и управления физическими величинами.

Я уже успел получить некоторую базовую функциональность с помощью __str__, __get/setitem__ и __truediv__ для нижележащих MySeries MyDataFrame (в обертке панды серии):

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), чтобы проверить тип self или other. Однако, прочитав больше о полиморфизме в Python (here), мне стало интересно, как другие будут реализовывать такие полиморфные двоичные операции.

Сообщите мне, если я должен дать некоторые разъяснения.

PS: В стороне. Я заметил, что в попытке имитировать панда синтаксического I`m письмо оберток, такие как

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

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

Любых советы о перенаправлении всех метод обычных панд вызовов со стороны панды класса MyDataFrame/MySeries?

Btw, я получаю сцепку, что пришло время для меня, чтобы вникать в документы Питона ...

ответ

0

К сожалению, нет никакого другого пути. Полиморфизм уже использовался путем реализации mul для каждого типа Pandas, поэтому соответствующий оператор ведет себя по-разному по типу первого аргумента. Однако для второго аргумента вы должны проверить тип. В статических языках это было бы сделано перегрузкой функции, основанной на втором типе аргументов, но в Python вам нужно использовать isinstance. Даже стандартная библиотека Python сама использует этот подход, если вы посмотрите на источник.

+0

Спасибо за объяснение. Обработка с помощью 'isistance' для меня в порядке, если она не справляется с трудностями при обработке основных типов Pint: например. 'type (_u (" meter "))' возвращает 'pint.unit.build_unit_class. .Unit', где я ожидаю, что он вернет что-то вроде 'Unit'. Любая подсказка? – balletpiraat

+1

Не используйте 'type', он игнорирует подклассы.Используйте 'isinstance (_u (« meter »), Unit)' вместо –

+0

Это уже многое разъясняет, однако вышеприведенное возвращает 'name 'Unit' не определено', что заставляет меня думать, что' import pint' недостаточно, чтобы сделать Python осведомленным класса «Unit» Пинта. Кстати, я работаю в ноутбуке Jupyter, если это имеет значение. Будет ли решение быть чем-то вроде «из единицы импорта пинты»? – balletpiraat

Смежные вопросы