制作OOP代码FP的Python装饰器;好的还是坏的?

时间:2014-06-20 00:44:48

标签: python oop

最近,我一直试图找出一个解决'表达问题'的方法,即在OOP或FP(函数式编程)中实现我的代码。我用来说明我的问题的例子是Vector2D类。我可以创建一个包含2D向量的所有必要函数的类(点积,幅度等),或者我可以创建一组函数,它们采用表示向量的2元组。我选择了哪个选项?

为了解决这个问题,我认为制作一个采用类方法并将它们转换为全局函数的装饰器可能会很好。我就这样做了:

import types

def function(method):
    method._function = True
    return method

def make_functions(cls):
    for key in cls.__dict__:
        method = getattr(cls, key)
        if not isinstance(method, types.FunctionType):
            continue
        if hasattr(method, '_function') and method._function:
            globals()[method.__name__] = method
    return cls

@make_functions
class Vector2D:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%g, %g)' % (self.x, self.y)

    def __iter__(self):
        for component in self.x, self.y:
            yield component

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

    def __setitem__(self, key, val):
        if key == 0:
            self.x = val
        elif key == 1:
            self.y = val
        else:
            print('not cool man')

    def __add__(self, other):
        x = self[0] + other[0]
        y = self[1] + other[1]
        return self.__class__(x, y)
    __radd__ = __add__

    def __sub__(self, other):
        x = self[0] - other[0]
        y = self[1] - other[1]
        return self.__class__(x, y)

    def __rsub__(self, other):
        x = other[0] - self[0]
        y = other[1] - self[1]
        return self.__class__(x, y)

    def __mul__(self, other):
        x = other * self[0]
        y = other * self[1]
        return self.__class__(x, y)
    __rmul__ = __mul__

    @function
    def dot_product(self, other):
        return self[0]*other[1] + self[1]*other[0]

现在,dot_product不仅是Vector2D类的方法,而且它也是一个全局函数,它接收两个向量(或类似矢量的对象)。这满足了实现这样的对象的功能和面向对象的方法。我可以预见这种方法的唯一问题是,任何可以表示为另一个对象(如元组或列表)的类必须被定义为以与它相似的对象的相同方式工作。这对于也可以是元组的Vector来说并不是那么糟糕,因为我们所要做的就是定义__getitem____iter__方法,但是我可以看到这种方法对于有多个对比实现

这是解决问题的公平方法吗?这是不好的做法还是技术?我应该单独提供一个还是其他的?

1 个答案:

答案 0 :(得分:1)

Python有一个@staticmethod装饰器,用于在没有该类实例化的情况下使用类方法。只需使用静态方法包装器注释类方法(注意该方法现在不采用自引用),您可以从类本身调用它。

在您的情况下,对于点积,只需执行:

class Vector2D():
    # Magic methods here...

    @staticmethod
    def dot_product(a, b):
        return a[0]*b[1] + a[1]*b[0]

然后,只需致电Vector2D.dot_product(my_vector1, my_vector2)即可使用Vector2D类本身的功能。

将类方法分配给全局函数听起来像一个非常危险,错误,复杂和冗长的解决方案。我会不惜一切代价避免它。