在数值工作中混合numpy和OO

时间:2012-09-19 19:22:48

标签: python performance oop numpy numerical

首先,我想知道在数值工作中使用面向对象方法是否是一般的好习惯。

其次,OO的一个可能用例是将某些模型的参数封装在某个对象中。说,我想学习形式为ax ^ 2 + bx + c的抛物线。所以我会在一些Parabola对象中封装a,b,c。我可以绘制它等等。现在,让我们说,我想探索抛物线垂直轴的位置。基本上,没有OO,我可以只绘制所有垂直轴位置的表面w.r.t.对于一些给定的c值,a和b(可能是两个numpy数组)。

我的问题是,我如何使用额外的OO层进行这样的表面绘图,而不会牺牲(太多)numpy性能?

额外说明

采用OO方法的一种方法是为参数a和b的一系列值创建一个抛物线对象矩阵。但是这种方式可以处理可能非常大的对象,而不是参数范围的普通numpy数组。

2 个答案:

答案 0 :(得分:2)

我建议不要使用对象数组,因为你最终会失去使用numpy几乎所有的性能优势。我们的结构或代码更像是这样:

class Points:

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

    def shift_left(self, distance):
        self.x -= distance

x = np.zeros(10000)
y = np.zeros(10000)

points_obj = Points(x, y)

现在,您可以创建在points_obj上运行的函数,方法等,因为points_obj.xpoint_obj.y是numpy数组(可能大小为1,或者可能更大)。如果您需要能够索引到points_obj,则可以始终在班级上定义__getitem__方法。

答案 1 :(得分:1)

您可以使用相同的数值算法,无论是否有面向对象。我真的不明白你的问题。 OO更多的是关于程序结构和数据之间的联系。方法中的数字可以与正常程序程序中的数字相同。 --edit -

当您对其方法进行矢量化时,您可以非常快速地制作抛物线阵列。你当然可以将更复杂的矢量化。

import numpy as np

class parabola:
    a = 0.0
    b = 0.0
    c = 0.0
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c
    def set_a(self, new_a):
        self.a = new_a
    def set_b(self, new_b):
        self.b = new_b
    def set_c(self, new_c):
        self.c = new_c
    def get_a(self):
        return self.a
    def get_b(self):
        return self.b
    def get_c(self):
        return self.c

vpara = np.vectorize(parabola)
vgeta = np.vectorize(parabola.get_a)
vgetb = np.vectorize(parabola.get_b)
vgetc = np.vectorize(parabola.get_c)


a = np.zeros(10000)
b = np.zeros(10000)
c = np.zeros(10000)
a[:]  = [i for i in xrange(10000)]
b[:]  = [2*i for i in xrange(10000)]
c[:]  = [i*i for i in xrange(10000)]

objs = np.empty((10000), dtype=object)
objs[:] = vpara(a,b,c)

print vgeta(objs[1:10:2]),vgetc(objs[9900:9820:-3])