首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线性代数结构

线性代数结构
EN

Code Review用户
提问于 2012-11-09 20:20:45
回答 1查看 175关注 0票数 1

我用线性代数作为我的基础。我想要做的一个非常具体的更改是,假设所有未定义的组件都是零(所有点和向量都有无限个组件;等式测试一旦检查两个组件返回“未定义”),就允许在点和向量之间进行相等测试。大多数情况下,我想这样做只是因为这样做似乎很酷,所以这并不是很重要。

但本质上,我只是希望有人拆开这段代码,告诉我为什么我做错了一切(或者告诉我,我做的一切都很好)。我们的目标只是拥有一个很好的,健全的PointVector系统,它非常灵活,任何人都可以理解--任何人都可以使用--以达到他们想要的任何目的。我构建的所有代码都将依赖于下面的代码,因此我希望确保我的设计模式是合理和灵活的。

代码语言:javascript
复制
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
EN

回答 1

Code Review用户

回答已采纳

发布于 2012-11-09 23:27:15

代码语言:javascript
复制
import math, sys, os

TOLERANCE = 0.00001

class SizeError(Exception):
    def __init__(self, *args):
        self.args = args
        print "Size Error between " + str(args)

不应该在异常构造函数中打印。最多应该为打印目的定义一个__repr__。但是,如果不这样做,并且信任缺省值,你很可能可以逃脱惩罚。

代码语言:javascript
复制
class P(object):

这个名字没有给我多少关于这门课的线索。

代码语言:javascript
复制
    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)。实际上,考虑完全不存储大小,而只是查看组件的大小。我还建议不要接受三种不同的传递参数的方式。选一个,让它在任何地方都能使用。

代码语言:javascript
复制
    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))

它会照顾好你的一切

代码语言:javascript
复制
        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):

你不需要零。

代码语言:javascript
复制
            result = self[i] - other[i]
            if math.fabs(result) > TOLERANCE:

我会把这两句话结合起来

代码语言:javascript
复制
                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,其他)

代码语言:javascript
复制
        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):

我不会让向量从点继承。我会让他们都继承其他一些更通用的类。向量不是一个点,像它这样的编码可能会令人困惑。

代码语言:javascript
复制
    def dotProduct(self, other):

Python约定是有用于方法的lowercase_with_underscores名称。

代码语言:javascript
复制
        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

在这里我会用

代码语言:javascript
复制
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这样的扩展中实现这样的东西。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/18418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档