最近,我一直试图找出一个解决'表达问题'的方法,即在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__
方法,但是我可以看到这种方法对于有多个对比实现
这是解决问题的公平方法吗?这是不好的做法还是技术?我应该单独提供一个还是其他的?
答案 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
类本身的功能。
将类方法分配给全局函数听起来像一个非常危险,错误,复杂和冗长的解决方案。我会不惜一切代价避免它。