python - 在 python: 标准列表 vs numpy array 中,容器列表

  显示原文与译文双语对照的内容

编写一些 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插入的数据的方法,但不需要修改列表:


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

有有效的方法来做这个?

谢谢!

时间: 原作者:

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

下面是 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(),但是我们需要绑定 NAME e,以便可以调用 e.calculate_result(i).real,因为可以使用任何类型的接口。

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


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)的元组,其中 eelement_list的元素,i 是来自 xrange(10000)的数字。 然后 it.imap() 将调用该函数并将tuple作为参数传递。 那么 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 just-in-time编译器("") 生成更好的代码。 我不知道JIT是否只能帮助 10000个调用,但看起来应该是尝试它的方法。

原作者:

你可以将结果放入到 array 中,通过在实例化时传递该视图进入到中。 如果访问数据的频率比调用类方法要更新的频繁,那么应该可以。

类似下面的内容。


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))

原作者:
...