2

我正在编写一些需要存储和访问不同类型元素列表的 python 代码。此列表的每个元素将属于不同的类类型。例如:

def file_len(fname):
    i = 0
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1

element_list = [ ]
data = np.loadtxt(filename)


if file_len(filename) == 1 : 
            data = np.loadtxt(filename)
            param1 = data[0]
            param2 = data[1]
            element_list.append(Class1.Class1(param1,param2))
else:
    for field in data:
                    param1 = field[0]
                    param2 = field[1]
                    element_list.append(Class1.Class1(param1, param2)

稍后我将需要多次访问插入在 element_list 上的 Class1 中的方法,但不需要修改列表:

for i in xrange(10000):
    for element in element_list:
        result += element.calculate_result(i).real #the results will be complex

有没有一种有效的方法来做到这一点?

谢谢!

4

2 回答 2

1

这不是一个完整的答案,但我发现了两件我可以贡献的东西。

这是一个改进的版本file_len()。如果文件长度为零,则此选项将返回 0。您的函数为长度为零的文件返回 1,为只有一行的文件返回 1。

def file_len(fname):
    i = 0
    with open(fname) as f:
        for i, l in enumerate(f, 1):
            pass
    return i

这是进行计算循环的更快方法。

result = sum(e.calculate_result(i).real for i in xrange(10000) for e in element_list)

使用 可能会使其更快reduce(),但我认为它不会更快。最大的节省reduce()是如果您可以避免一遍又一遍地绑定名称,但是我们需要绑定名称e,以便我们可以调用e.calculate_result(i).real,即使类型e可以是任何东西。

如果你能做这样的事情,它可能会快一点。

import itertools as it
import operator as op
result = reduce(op.add, it.imap(SomeClass.calculate_something, it.product(element_list, xrange(10000))))

同样,主要的节省是避免绑定名称。 it.product()返回元组,其中包括(e, i)wheree是来自的元素element_list和来自i的数字xrange(10000)。然后it.imap()将调用该函数并将元组作为参数传递。然后reduce()将总结一切。实际上,只是跟注sum()可能和其他方法一样好,reduce(op.add)但您可以尝试两种方法,看看是否其中一种方法比另一种略快。如果你能找出一些合理的东西,SomeClass.calculate_something那么也许你可以做到这一点。

嗯,可能值得尝试让sum()(或reduce())计算一个复杂的总和,然后在总和完成后丢弃虚部。这会比.real每个值访问一次属性更快吗?我不确定,但它可能会帮助您使reduce()版本正常工作。

编辑:

您应该尝试在 PyPy 下运行您的程序。

http://pypy.org/

如果你这样做,请务必使用这一行而不是我展示的第一行:

result = sum(e.calculate_result(i).real for e in element_list for i in xrange(10000))

这样,您可以e连续使用每个元素进行 10000 次调用,这应该有助于 PyPy 即时编译器(“JIT”)生成更好的代码。我不知道 JIT 是否只对 10000 个呼叫有帮助,但似乎这应该是尝试它的方法。

于 2012-06-13T09:18:21.050 回答
0

您可以通过在实例化时传递该视图将类中的结果放入数组中的视图中。如果您访问数据的频率高于调用类方法来更新数据的频率,那么这应该可行。

类似于以下内容...

def file_len(fname):
    i = 0
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1

element_list = [ ]
data = np.loadtxt(filename)


array_idx = 0

# length_of_data is the number of elements that will be in element_list
result_array = numpy.zeros(length_of_data, dtype='complex128')

if file_len(filename) == 1 : 
    data = np.loadtxt(filename)
    param1 = data[0]
    param2 = data[1]
    element_list.append(Class1.Class1(param1, param2, 
                            result_array[array_idx:array_idx+1]))
    array_idx += 1
else:
    for field in data:
        param1 = field[0]
        param2 = field[1]
        element_list.append(Class1.Class1(param1, param2,
                            result_array[array_idx:array_idx+1])
        array_idx += 1

在类中,您将直接更新视图。考虑这个最小的例子:

import numpy

a = numpy.zeros(5, dtype='complex128')

class Foo(object):

    def __init__(self, real, imag, array_view):
        self._array_view = array_view
        self._array_view[:] = real + 1j*imag #<--- The [:] is needed


element_list = []
for n in range(0, len(a)):
    element_list.append(Foo(n, n+1, a[n:n+1]))

print(a)
print(numpy.sum(a))
于 2012-06-13T07:58:11.213 回答