简体   繁体   English

在Python 3.6中实现不同功能“捆绑”的设计模式

[英]Design pattern for implementing different “bundles” of functions in Python 3.6

so I have a set of distance functions and respective calculations, eg average, comparison 所以我有一组距离函数和相应的计算,例如平均值,比较

and I want to be able to iterate over those different distances to compute their values/averages/whatevers, and make it easy to add new distances 而且我希望能够遍历这些不同的距离以计算其值/平均值/任何值,并轻松添加新的距离

Right now, I'm doing that by using nested dictionaries, however this depends on all the functions existing and working properly, so I was wondering whether there is a design pattern that solves that? 现在,我正在使用嵌套字典来完成此操作,但是这取决于现有的所有功能并正常工作,所以我想知道是否存在一种可以解决此问题的设计模式?

My first idea was a metaclass that defines which functions need to exist and classes that implement these functions. 我的第一个想法是一个元类,它定义需要存在的功能以及实现这些功能的类。 However, then there would be no meaningful instances of those Distance classes. 但是,这些Distance类将没有有意义的实例。 My second idea then was defining a Distance class and have the functions as attributes of that class, but that seems bad style. 然后,我的第二个想法是定义一个Distance类,并将这些函数作为该类的属性,但是这似乎很糟糕。 Example for the second Idea: 第二个想法的示例:

class Distance:
    def __init__(self, distf, meanf):
        self.distf = distf
        self.meanf = meanf

    def dist(self, x1,x2):
        return self.distf(x1,x2)

    def mean(self, xs):
         return self.meanf(xs)

    d = Distance(lambda x,y: abs(x-y), np.mean)

    d.dist(1,2) ##returns 1 as expected
    d.dist([1,2]) ## returns 1.5 as expected

this works (and also enforces the existence/maybe even properties of the functions), but as stated above feels like rather bad style. 这是行得通的(并且还强制执行了功能的存在/甚至是功能的属性),但是如上所述,这感觉像是一种很糟糕的样式。 I do not plan to publish this code, its just about keeping it clean and organized if that is relevant. 我不打算发布此代码,如果相关的话,仅用于保持代码整洁有序。 I hope the question is clear, if not pleas dont hesitate to comment and I will try to clarify. 我希望这个问题是明确的,如果没有,请不要犹豫,我将尽力澄清。

EDIT: - @victor: Everything should be initially set. 编辑:-@victor:应该首先设置所有内容。 At runtime only selection should occur. 在运行时,仅应进行选择。 - @abarnert Mostly habitual, also to restrict usage (np.mean needs to be called without axis argument in this example), but that should hopefully not be relevant since I'm not publishing this - @juanpa gonna look into that -@abarnert通常是习惯性的,也是为了限制使用(在此示例中,np.mean需要在没有轴参数的情况下被调用),但是由于我不打算发布此代码,因此希望它不相关-@juanpa会调查

It seems that simple inheritance is what you need. 似乎简单的继承就是您所需要的。 So, you create a base class BaseSpace which is basically an interface: 因此,您将创建一个基类BaseSpace ,该基类基本上是一个接口:

from abc import ABC

class BaseSpace(ABC):
    @staticmethod
    def dist(x1, x2):
        raise NotImplementedError()

    @staticmethod
    def mean(xs):
        raise NotImplementedError()

Then you just inherit this interface with all different combinations of the functions you need, implementing the methods either inside the class (if you are using them once only) or outside, and just assigning them in the class definition: 然后,您可以使用所需功能的所有不同组合继承该接口,在类内部(如果仅使用它们一次)或外部实现方法,并在类定义中分配它们:

class ExampleSpace(BaseSpace):
    @staticmethod
    def dist(x1, x2):
        return abs(x1 - x2)

    mean = staticmethod(np.mean)

Because of the Python's duck typing approach (which is also applicable to interface definition) you don't really need the base class actually defined, but it helps to show what is expected of each of your "Space" classes. 由于Python的鸭子输入法(也适用于接口定义),您实际上并不需要实际定义的基类,但是它有助于显示每个“ Space”类的期望。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM