在 class Python 中传递参数的最佳实践

Best Practice for passing arguments in a class Python

我是 OOP 的新手,我很确定我解决问题的方式不是最聪明的。

我正在构建自定义 K 均值算法,并希望为不同的距离函数提供选项。

我即将解决的方法是构建 if 语句并分别计算距离。

例如:

class ExampleDist():
    def __init__(self, measure="euklid"):
        self.measure = measure
    
    def euklid_distance(x_1,x_2):
        dist = np.linalg.norm(x_1-x_2)
        return dist
    
    def abs_distance(x_1,x_2):
        dist = np.absolute(x_1-x_2)
        return dist
    
    def dist(self, x_1, x_2):
        if(self.measure == "euklid"):
            self.dist = euklid_distance(x_1,x_2)
        elif(self.measure == "abs"):
            self.dist = abs_distance(x_1,x_2)

dist1 = ExampleDist(measure = "euklid")
dist1.dist(np.array([1,1]),np.array([0,2]))

但是在 K 均值算法中,我必须复制粘贴计算数据点和质心之间距离的整个循环,并且只更改距离。

复制粘贴从来都不是一个好的解决方案,所以我希望有一个解决方案可以自动传递我想使用的距离度量。 像这样(伪代码):

class ExampleDist():
    def __init__(self, measure="euklid"):
        self.measure = measure
    
    def euklid_distance(x_1,x_2):
        dist = np.linalg.norm(x_1-x_2)
        return dist
    
    def abs_distance(x_1,x_2):
        dist = np.absolute(x_1-x_2)
        return dist
    
    def dist(self, x_1, x_2):
        self.dist = [self.meassure]_distance(x_1,x_2)

dist1 = ExampleDist(measure = "euklid")
dist1.dist(np.array([1,1]),np.array([0,2]))

为什么不只创建一个 dist 函数,例如:

class ExampleDist():
    def __init__(self, measure="euklid"):
        self.measure = measure

    def dist(self, x_1, x_2):
        if self.measure == 'euklid':
            return np.linalg.norm(x_1-x_2)
        elif self.measure == 'absolute':
            return np.absolute(x_1-x_2)
        else:
            return None

假设您将要拥有的所有距离函数都将接受相同的参数(x1x2),您可以使用字典在距离类型和距离函数之间进行映射.

这是实现这一目标的最具扩展性和灵活性的方法之一。

class ExampleDist():
    _distance_funcs = {'euclid': np.linalg.norm,
                       'abs': np.absolute}  
                        # or implement your own wrappers as in your example

    def dist(self, x1, x2, measure):
        try:
            return self._distance_funcs[measure](x1, x2)
        except KeyError:
            raise ValueError(f"`measure` should be one of {', '.join(self._distance_funcs.keys())}")