【问题标题】:How to avoid re-defining a class that differs just for inputs and outputs data type conversions from another class?如何避免重新定义一个仅与另一个类的输入和输出数据类型转换不同的类?
【发布时间】:2021-06-29 11:33:19
【问题描述】:

我有一个有两种方法的类:“fit”和“transform”。这些方法应该适用于特定的数据类型(多索引 pandas DataFrame),但我想将它与另一种数据类型(numpy 3d 数组)一起使用,但复制和粘贴类对我来说似乎并不方便,只是在输入和输出中添加数据转换。

这里的 DRY 最佳做法是什么?在方法上使用装饰器?

下面是我的意思的简单伪代码

import numpy as np
import pandas as pd


class Transformer2d:

  def __init__(self):
    pass

  def fit(self, X, y):
    self.foo = np.mean(X['0'])
    return self

  def transform(self, X):
    X['0'] = X['0'] / self.foo
    return X


class Transformer3d:
  """
  I would not like to create this class because is very similar 
  to the previous one except for data type conversion for inputs and outputs
  """

  def __init__(self):
    pass

  def fit(self, X, y):
    X_ = threedim2twodim(X)  # difference with the previous class
    self.foo = np.mean(X_['0'])
    return self

  def transform(self, X):
    X_ = threedim2twodim(X)  # difference with the previous class
    X_['0'] = X_['0'] / self.foo
    return twodim2threedim(X_, X.shape[0])  # difference with the previous class


# data type conversion functions
def threedim2twodim(X:np.ndarray):
    return X.swapaxes(2, 1).reshape(-1, X.shape[1])


def twodim2threedim(X:np.ndarray, n_samples:int=-1):
    return X.reshape(n_samples, -1, X.shape[1]).swapaxes(1, 2)

【问题讨论】:

    标签: python oop methods decorator


    【解决方案1】:

    您可以为此使用functools.singledispatchmethod。一个简单的演示是重载类的 __init__() 函数以采用整数或浮点数,并让类根据输入类型具有不同的行为。

    from functools import singledispatchmethod
    
    class Point:
        @singledispatchmethod
        def __init__(self, x: int, y: int):
            self.x = x
            self.y = y
    
        @__init__.register
        def _(self, x: float, y:float):
            self.x = int(x)
            self.y = int(y)
    
        def norm(self):
            return self.x**2 + self.y**2
    
        
    integer_p = Point(3,4)
    print(f"Int norm: {integer_p.norm()}")
    
    float_p = Point(3.1, 4.2)
    print(f"Float norm: {float_p.norm()}")
    

    这样您就不必使用isinstance 自己进行任何类型检查。

    【讨论】:

      【解决方案2】:

      在您的方法中,您可以检查输入的type() 并决定您希望对身体的其余部分做什么。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-24
        • 2022-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多