我正在编写一些需要存储和访问不同类型元素列表的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
有一种有效的方法吗?
谢谢!
答案 0 :(得分: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)
的元组,其中e
是来自element_list
的元素,而i
是来自xrange(10000)
的数字。然后it.imap()
将调用该函数并将元组作为参数传递。然后reduce()
将总结一切。实际上,只是调用sum()
可能与reduce(op.add)
一样好,但你可以尝试两种方式,看看其中一个是否比另一个略快。如果你能找到SomeClass.calculate_something
合理的东西,那么也许你可以做到这一点。
sum()
(或reduce()
)计算一个复数和,然后在总和完成时扔掉虚部。这会比每个值访问一次.real
属性更快吗?我不确定,但它可能有助于您使reduce()
版本正常工作。
编辑:
您应该尝试在PyPy下运行您的程序。
如果你这样做,请务必使用此行而不是我显示的第一行:
result = sum(e.calculate_result(i).real for e in element_list for i in xrange(10000))
这样,您连续使用每个元素e
进行10000次调用,这有助于PyPy即时编译器(“JIT”)生成更好的代码。我不知道JIT是否会帮助只有10000次通话,但看起来这应该是尝试它的方式。
答案 1 :(得分: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))