考虑以下最小问题:
from math import sqrt
class Vector(object):
def __init__(self, x, y, z):
self.v = [x, y, z]
def normalize(self):
x, y, z = self.v
norm = sqrt(x**2 + y**2 + z**2)
self.v = [x/norm, y/norm, z/norm]
# other methods follow
class NormalizedVector(Vector):
def __init__(self, x, y, z):
super(Vector, self).__init__(x, y, z)
self.normalize()
因此,基本上NormalizedVector对象与Vector对象相同,但添加了规范化。
是否可以向Vector添加一个方法,以便每当调用normalize方法时,对象会自动子类化为NormalizedVector?
我知道我可以使用abstract factory pattern,但这只有在创建时对象被子类化时才会起作用:我希望能够创建先前已创建的对象的子类。
我发现some solutions基于重新分配__ class __方法,但不建议这样做。我愿意将上面的模式修改为更“Pythonic”的模式。
答案 0 :(得分:2)
我建议只使用 Vector()类和布尔normalized
实例属性。
此外,在normalize
方法中,您使用的是 x , y 和 z ,但这些变量未定义且您是甚至没有用self
阅读它们。
我建议的代码:
from math import sqrt
class Vector(object):
def __init__(self, x, y, z, normalized=False):
self.v = [x, y, z]
if normalized in [True, False]:
self.normalized = normalized
else:
raise Exception("Please set normalized to either True or False")
def __repr__(self):
return "Vector ({}, {}, {})".format(*self.v)
def normalize(self):
x,y,z = self.v
norm = sqrt(x**2 + y**2 + z**2)
self.v = [x/norm, y/norm, z/norm]
self.normalized = True
def isNormalized(self):
return self.normalized
# other methods follow
v1 = Vector(10, 20, 30)
print v1.isNormalized()
v1.normalize()
print v1.isNormalized()
v2 = Vector(40, 50, 60, normalized=True)
print v2.isNormalized()
<强>输出:强>
False
True
True
__ repr __ 功能只会显示您对象的良好表现形式:
print v1
<强>输出:强>
Vector (0.267261241912, 0.534522483825, 0.801783725737)
答案 1 :(得分:1)
为什么需要跟踪矢量本身的规范化,只需在main.py
或您使用矢量的任何地方跟踪它?
另外,我只是返回带有规范化值的对象的新副本。这样,您可以在计算中动态创建标准化向量,而无需更改原始向量。
from math import sqrt
class Vector(object):
def __init__(self, x, y, z):
self.v = [x, y, z]
def normalized(self):
x, y, z = self.v
norm = sqrt(x**2 + y**2 + z**2)
return Vector(x/norm, y/norm, z/norm)
如果你有很多矢量你需要规范化,你可以将它们规范化为两个列表或一个元组列表或任何你想要的,这是一个字典的例子:
vectors = {}
for x, y, z in zip(range(10), range(10), range(10)):
v = Vector(x, y, z)
vectors[v] = v.normalize()
如果您只是有一些向量或随机需要对矢量进行标准化以进行计算,您可以手动跟踪它们或在计算中动态创建它们而不更改原始向量:{{ 1}}。
答案 2 :(得分:0)
如果你真的想保留这两个类,你可以覆盖这些类的操作。
我们假设您要添加向量和规范化向量。你可以这样做
来自math import sqrt
class Vector:
def __init__(self,x,y):
self.x = x
self.y = y
def __add__(self,v):
if isinstance(v,Vector):
return (self.x+v.x,self.y+v.y)
elif isinstance(v,NormVector):
n = NormVector(self.x,self.y)
return (n.x+v.x,n.y+v.y)
class NormVector:
def __init__(self,x,y):
self.x = x / sqrt(x**2 + y**2)
self.y = y / sqrt(x**2 + y**2)
def __add__(self,v):
if isinstance(v,Vector):
n = NormVector(v);
return (self.x + n.x,self.y + n.y)
elif isinstance(v,NormVector):
return (self.x+v.x,self.y+v.y)
a = Vector(5,0)
b = NormVector(0,3)
c = a + b
print c
像这样你可以覆盖你需要的任何功能。您可以在documentation
中找到可能的操作列表