我用线性代数作为我的基础。我想要做的一个非常具体的更改是,假设所有未定义的组件都是零(所有点和向量都有无限个组件;等式测试一旦检查两个组件返回“未定义”),就允许在点和向量之间进行相等测试。大多数情况下,我想这样做只是因为这样做似乎很酷,所以这并不是很重要。
但本质上,我只是希望有人拆开这段代码,告诉我为什么我做错了一切(或者告诉我,我做的一切都很好)。我们的目标只是拥有一个很好的,健全的Point和Vector系统,它非常灵活,任何人都可以理解--任何人都可以使用--以达到他们想要的任何目的。我构建的所有代码都将依赖于下面的代码,因此我希望确保我的设计模式是合理和灵活的。
import math, sys, os
TOLERANCE = 0.00001
class SizeError(Exception):
def __init__(self, *args):
self.args = args
print "Size Error between " + str(args)
class P(object):
def __init__(self, *args):
if len(args) == 1:
try:
self.components = tuple(args[0])
self.size = len(args[0])
except TypeError:
self.components = tuple(args)
self.size = len(args)
else:
self.components = args
self.size = len(args)
def __getitem__(self, key):
return self.components[key]
def __repr__(self):
result = ""
for i in range(0, self.size):
result += str(self[i]) + ", "
return "<Point (" + str(self.size) + ") : " + result[:-2] + ">"
def __eq__(self, other):
if self.size != other.size:
raise SizeError(self, other)
for i in range(0, self.size):
result = self[i] - other[i]
if math.fabs(result) > TOLERANCE:
return False
return True
def __add__(self, other):
if other.size != self.size:
raise SizeError(self, other)
result = []
for i in range(0, self.size):
result.append(self[i] + other[i])
return P(result)
def __sub__(self, other):
if other.size != self.size:
raise SizeError(self, other)
result = []
for i in range(0, self.size):
result.append(self[i] - other[i])
return V(result)
class V(P):
def __repr__(self):
result = ""
for i in range(0, self.size):
result += str(self[i]) + ", "
return "<Vector (" + str(self.size) + ") : " + result[:-2] + ">"
def __add__(self, other):
if other.size != self.size:
raise SizeError(self, other)
result = []
for i in range(0, self.size):
result.append(self[i] + other[i])
return V(result)
def __mul__(self, scalar):
result = []
for i in range(0, self.size):
result.append(self[i] * scalar)
return V(result)
def __neg__(self):
return self * -1
def dotProduct(self, other):
result = 0
if self.size != other.size:
raise SizeError(self, other)
for i in range(0, self.size):
result += self[i] * other[i]
return result
def normalize(self):
result = []
length = self.getLength()
if math.fabs(length) < TOLERANCE: return self.getZero()
for i in range(0, self.size):
result.append(self[i] / length)
return V(result)
def getLength(self):
result = 0
for i in range(0, self.size):
result += self[i]**2
return math.sqrt(result)
def getZero(self):
return self * 0
def isZero(self):
zero = self.getZero()
return self == zero发布于 2012-11-09 23:27:15
import math, sys, os
TOLERANCE = 0.00001
class SizeError(Exception):
def __init__(self, *args):
self.args = args
print "Size Error between " + str(args)不应该在异常构造函数中打印。最多应该为打印目的定义一个__repr__。但是,如果不这样做,并且信任缺省值,你很可能可以逃脱惩罚。
class P(object):这个名字没有给我多少关于这门课的线索。
def __init__(self, *args):
if len(args) == 1:
try:
self.components = tuple(args[0])
self.size = len(args[0])
except TypeError:
self.components = tuple(args)
self.size = len(args)
else:
self.components = args
self.size = len(args)与其三次分配大小,不如在最后使用self.size = len(self.components)。实际上,考虑完全不存储大小,而只是查看组件的大小。我还建议不要接受三种不同的传递参数的方式。选一个,让它在任何地方都能使用。
def __getitem__(self, key):
return self.components[key]
def __repr__(self):
result = ""
for i in range(0, self.size):
result += str(self[i]) + ", "添加字符串是昂贵的。但是python有一个非常好的连接函数。所以你可以:
.join(地图(str,self))
它会照顾好你的一切
return "<Point (" + str(self.size) + ") : " + result[:-2] + ">"
def __eq__(self, other):
if self.size != other.size:
raise SizeError(self, other)
for i in range(0, self.size):你不需要零。
result = self[i] - other[i]
if math.fabs(result) > TOLERANCE:我会把这两句话结合起来
return False
return True
def __add__(self, other):
if other.size != self.size:
raise SizeError(self, other)
result = []
for i in range(0, self.size):
result.append(self[i] + other[i])使用zip,使用列表理解会更快一些:
结果= 用zip表示x,y的x+y(self,其他)
return P(result)
def __sub__(self, other):
if other.size != self.size:
raise SizeError(self, other)
result = []
for i in range(0, self.size):
result.append(self[i] - other[i])
return V(result)
class V(P):我不会让向量从点继承。我会让他们都继承其他一些更通用的类。向量不是一个点,像它这样的编码可能会令人困惑。
def dotProduct(self, other):Python约定是有用于方法的lowercase_with_underscores名称。
result = 0
if self.size != other.size:
raise SizeError(self, other)
for i in range(0, self.size):
result += self[i] * other[i]
return result在这里我会用
return sum(x * y for x, y in zip(self, other))
def normalize(self):
result = []
length = self.getLength()
if math.fabs(length) < TOLERANCE: return self.getZero()
for i in range(0, self.size):
result.append(self[i] / length)
return V(result)
def getLength(self):
result = 0
for i in range(0, self.size):
result += self[i]**2
return math.sqrt(result)
def getZero(self):
return self * 0
def isZero(self):
zero = self.getZero()
return self == zero这两种实现都将是无效的。他们应该工作,但他们会相对缓慢。事实上,在python中实现的任何Point/Vector都是不可饶恕的慢。这就是为什么我们通常在像numpy这样的扩展中实现这样的东西。
https://codereview.stackexchange.com/questions/18418
复制相似问题