我怀疑对于您的二维数组,定义对角线的方法比遍历行和计算这样的函数更好。但要专注于“延迟”函数评估的问题,我会试试这个:
定义一个简单的函数
In [438]: def func(x):
.....: return x**2
.....:
此列表定义不起作用,因为解释器在将x*i 传递给func 之前尝试评估它们。它将使用现有的 x 和 i。
In [442]: [func(x*i),func(x*i**2)]
...
NameError: name 'x' is not defined
相反,我可以将每个函数调用包装在另一个函数调用中。它可能是一个命名函数,或者像我在这里所做的一个未命名的lambda。就像func 的主体一样,x*i 被延迟到调用 lambda:
In [443]: [lambda x,i:func(x*i), lambda x,i: func(x*i**2)]
Out[443]: [<function __main__.<lambda>>, <function __main__.<lambda>>]
In [444]: flist=_ # assign that list to a new name for later use
现在我们可以定义 x 和 i 并评估列表中的函数:
In [445]: x=np.arange(3)
In [446]: i=2
In [447]: [f(x,i) for f in flist]
Out[447]: [array([ 0, 4, 16]), array([ 0, 16, 64])]
或者我们可以在 i 的迭代中包装它:
In [449]: [[f(x,i) for f in flist] for i in range(3)]
Out[449]:
[[array([0, 0, 0]), array([0, 0, 0])],
[array([0, 1, 4]), array([0, 1, 4])],
[array([ 0, 4, 16]), array([ 0, 16, 64])]]
我什至可以将其变成 3d 数组:
In [450]: np.array(_)
Out[450]:
array([[[ 0, 0, 0],
[ 0, 0, 0]],
[[ 0, 1, 4],
[ 0, 1, 4]],
[[ 0, 4, 16],
[ 0, 16, 64]]])
另一种方法是参数化包装函数
In [451]: def func1(x,i,p=1):
.....: return func(x*i**p)
In [452]: [[func1(x,i,p) for p in [1,2]] for i in range(3)]
Out[452]:
[[array([0, 0, 0]), array([0, 0, 0])],
[array([0, 1, 4]), array([0, 1, 4])],
[array([ 0, 4, 16]), array([ 0, 16, 64])]]
functools 有一个 partial 函数,可以让我在延迟完整评估的同时指定函数的一些参数:
partial(func, *args, **keywords) - 部分应用给定参数和关键字的新函数。
In [461]: from functools import partial
In [462]: flist=[partial(func1,p=1), partial(func1,p=2)]
In [463]: [[f(x,i) for f in flist] for i in range(3)]
Out[463]:
[[array([0, 0, 0]), array([0, 0, 0])],
[array([0, 1, 4]), array([0, 1, 4])],
[array([ 0, 4, 16]), array([ 0, 16, 64])]]
事实上,如果我调整 func1,我可以同时分配 i 和 p 部分:
In [464]: def func1(x,i=0,p=1):
return func(x*i**p)
In [465]: flist=[partial(func1,p=1), partial(func1,p=2)]
In [466]: fflist=[[partial(f,i=i) for f in flist] for i in range(3)]
In [467]: fflist
Out[467]:
[[functools.partial(<function func1 at 0xb4d3e3d4>, i=0, p=1),
functools.partial(<function func1 at 0xb4d3e3d4>, i=0, p=2)],
[functools.partial(<function func1 at 0xb4d3e3d4>, i=1, p=1),
functools.partial(<function func1 at 0xb4d3e3d4>, i=1, p=2)],
[functools.partial(<function func1 at 0xb4d3e3d4>, i=2, p=1),
functools.partial(<function func1 at 0xb4d3e3d4>, i=2, p=2)]]
评估这个仍然需要遍历嵌套列表:
In [471]: [[f(x) for f in ff] for ff in fflist]
Out[471]:
[[array([0, 0, 0]), array([0, 0, 0])],
[array([0, 1, 4]), array([0, 1, 4])],
[array([ 0, 4, 16]), array([ 0, 16, 64])]]
我可以通过一次调用 partial(对于每个“单元格”)来创建 fflist:
fflist=[[partial(func1,i=i,p=p) for p in [1,2]] for i in range(3)]
可以通过将fflist 设为对象 dtype 数组来简化迭代,但这是后一个问题。
还有其他包装函数以供以后评估的方法,但这些是最简单和最明显的。
我也可以将partial 与x 参数一起使用
In [478]: z=[[partial(f,x) for f in ff] for ff in fflist]
In [479]: z
Out[479]:
[[functools.partial(<function func1 at 0xb4d3e3d4>, array([0, 1, 2]), i=0, p=1),
functools.partial(<function func1 at 0xb4d3e3d4>, array([0, 1, 2]), i=0, p=2)],
....]]
In [480]: [[f() for f in ff] for ff in z]