在 python 中组合使用 max、xrange 和 lambda 函数
the use of combining max, xrange and lambda function in python
我找到了一个为 LU 分解旋转方阵的代码,但我无法理解其中的一些代码。
def pivotize(m):
"""Creates the pivoting matrix for m."""
n = len(m)
ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
for j in xrange(n):
row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
if j != row:
ID[j], ID[row] = ID[row], ID[j]
return ID
首先,ID 行不就是单位矩阵吗?这样做有什么好处吗?
其次,我不能真正理解行的行。我知道 lambda 用于在文本中定义一个函数,一旦提供了 i 的值(j 的值取决于 for 循环),它只是 returns M_ij 的值,但我是什么?
而且 xrange 不是类似于 range 吗?但是这里 return 是什么意思?
当与函数 max 结合使用时,会发生什么?就是不知道max函数里面有什么东西在比较。
抱歉,如果这个问题听起来很愚蠢。我是编程新手
First, isn't the line for ID simply the identity matrix?
是的。
Second, I can't really understand the line for row....
See this 讨论 max/key/lambda 互动。要回答 "what is i
?",它是 lambda 函数的参数,对于 foo
,i
等效于 x
。 (为清楚起见,分别生成 abs(m[x][j])
和 abs(m[foo][j])
)。
And isn't xrange similar to range?
是的。在 Python 2 xrange
returns 中,仅在需要时延迟计算下一个值的序列对象。 See this for more info。当完全循环时,range
和 xrange
将产生相同的结果,但实现不同。
But what does it return here?
第 5 行的 xrange(n)
将 return 从 0 到 (n-1) 的整数值,而第 6 行的 xrange(j, n)
将 return 从 j 到 ( n-1).
编辑
关于 lambda 的更多信息:
想一想如何将给定的数字序列加倍。首先定义一个将数字 x
和 return 加倍的函数。然后将该函数映射到序列的每个元素。
# Traditional
def double(x): return x*2
print map(double, [1,2,3,4]) # [2, 4, 6, 8]
您也可以使用匿名 (lambda) 函数来做同样的事情:
# Lambda
print map(lambda i: i*2, [1,2,3,4]) # [2, 4, 6, 8]
请注意,除了 double
函数的定义消失并且调用 map
中对该函数的引用被 "inline" lambda 替换之外,其他一切都是一样的功能。
编辑 2
And when combined with the function max, what happens?
这一行row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
可以分解如下:
xrange(j,n)
生成从j
(含)到n
(不含)的整数序列。
- 这些整数中的每一个然后 "passed" 作为键参数中函数的参数。换句话说,它们分别用作 lambda 函数中的
i
。 lambda 函数 "returns" 第 i
行和 j
列的绝对值。[1]
- 然后
max
函数找到这些 "lambda outputs" 的最大值并设置 row
等于它。
这也可以写成列表理解的最大值:
row = max( [abs(m[i][j]) for i in xrange(j,n)] )
或者正如 Dan D. 在他的评论中指出的那样,写成一个生成器表达式(不创建中间列表)简单地:
row = max( abs(m[i][j]) for i in xrange(j,n) )
备注:
[1] 这里有一些假设,但行列是表示矩阵的标准方式。
xrange
是一个 Python2 结构,用于处理 range
内存效率。 Beforerange
实际上创建了一个列表,然后 for
循环会 运行 通过它。 xrange
然而是一个生成器,这意味着它在被要求时一次吐出 1 个值,而不创建完整列表。
ID
其实就是一个单位矩阵。你就在那里。这是一个巧妙的技巧,可以将布尔值转换为值 1.0
.
的浮点数
然后代码段 运行 遍历所有剩余的行,并在原始矩阵 row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
中找到该行的最大值。请注意,这里有第二个不错的技巧,max
可以对任何可迭代对象进行操作,包括生成器。该行中的 lambda
关键字表示所谓的 "anonymous function"。
更多详细信息:匿名函数是未绑定到标识符的函数。代码段中的 Lambda 函数接受 1 个值,i
和 return 是矩阵位置 m[i][j]
处的绝对值。作为函数输入发送的值由生成器 xrange(j, n)
提供。
max
然后将 lambda 函数的 return 值作为它实际比较的对象。例如,在 python3 中无法比较 2 种不同的类型。 IE。比较 string > int 会产生:TypeError: unorderable types: str() > int()
。但是,如果我们确定该列表包含数字,只是格式不同,您可以执行以下操作:
>>> l = ["1", "2", 3, 4]
>>> max(l, key=lambda x: int(x))
4
>>> min(l, key=lambda x: int(x))
'1' #type 'str'
这只是表明,实际比较值是您的 key
函数的 return,但实际产生的值是您的原始输入值。
一旦它找到行最大值,它"rotates",通过替换ID[j], ID[row] = ID[row], ID[j]
,所有其他行,在单位矩阵,围绕它这样只有最大值留在对角线上。
这有助于防止在下一步的 LU 分解中除数过小。
您在 return 中得到的不是旋转后的原始矩阵,而是 1.0
s 和 0.0
s 的矩阵,即乘以original 将产生旋转矩阵。
这似乎是一个编写得很好的函数,可以节省内存并有助于 python 中的性能。希望我做对了。
我找到了一个为 LU 分解旋转方阵的代码,但我无法理解其中的一些代码。
def pivotize(m):
"""Creates the pivoting matrix for m."""
n = len(m)
ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
for j in xrange(n):
row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
if j != row:
ID[j], ID[row] = ID[row], ID[j]
return ID
首先,ID 行不就是单位矩阵吗?这样做有什么好处吗?
其次,我不能真正理解行的行。我知道 lambda 用于在文本中定义一个函数,一旦提供了 i 的值(j 的值取决于 for 循环),它只是 returns M_ij 的值,但我是什么?
而且 xrange 不是类似于 range 吗?但是这里 return 是什么意思?
当与函数 max 结合使用时,会发生什么?就是不知道max函数里面有什么东西在比较。
抱歉,如果这个问题听起来很愚蠢。我是编程新手
First, isn't the line for ID simply the identity matrix?
是的。
Second, I can't really understand the line for row....
See this 讨论 max/key/lambda 互动。要回答 "what is i
?",它是 lambda 函数的参数,对于 foo
,i
等效于 x
。 (为清楚起见,分别生成 abs(m[x][j])
和 abs(m[foo][j])
)。
And isn't xrange similar to range?
是的。在 Python 2 xrange
returns 中,仅在需要时延迟计算下一个值的序列对象。 See this for more info。当完全循环时,range
和 xrange
将产生相同的结果,但实现不同。
But what does it return here?
第 5 行的 xrange(n)
将 return 从 0 到 (n-1) 的整数值,而第 6 行的 xrange(j, n)
将 return 从 j 到 ( n-1).
编辑
关于 lambda 的更多信息:
想一想如何将给定的数字序列加倍。首先定义一个将数字 x
和 return 加倍的函数。然后将该函数映射到序列的每个元素。
# Traditional
def double(x): return x*2
print map(double, [1,2,3,4]) # [2, 4, 6, 8]
您也可以使用匿名 (lambda) 函数来做同样的事情:
# Lambda
print map(lambda i: i*2, [1,2,3,4]) # [2, 4, 6, 8]
请注意,除了 double
函数的定义消失并且调用 map
中对该函数的引用被 "inline" lambda 替换之外,其他一切都是一样的功能。
编辑 2
And when combined with the function max, what happens?
这一行row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
可以分解如下:
xrange(j,n)
生成从j
(含)到n
(不含)的整数序列。- 这些整数中的每一个然后 "passed" 作为键参数中函数的参数。换句话说,它们分别用作 lambda 函数中的
i
。 lambda 函数 "returns" 第i
行和j
列的绝对值。[1] - 然后
max
函数找到这些 "lambda outputs" 的最大值并设置row
等于它。
这也可以写成列表理解的最大值:
row = max( [abs(m[i][j]) for i in xrange(j,n)] )
或者正如 Dan D. 在他的评论中指出的那样,写成一个生成器表达式(不创建中间列表)简单地:
row = max( abs(m[i][j]) for i in xrange(j,n) )
备注:
[1] 这里有一些假设,但行列是表示矩阵的标准方式。
xrange
是一个 Python2 结构,用于处理 range
内存效率。 Beforerange
实际上创建了一个列表,然后 for
循环会 运行 通过它。 xrange
然而是一个生成器,这意味着它在被要求时一次吐出 1 个值,而不创建完整列表。
ID
其实就是一个单位矩阵。你就在那里。这是一个巧妙的技巧,可以将布尔值转换为值 1.0
.
然后代码段 运行 遍历所有剩余的行,并在原始矩阵 row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
中找到该行的最大值。请注意,这里有第二个不错的技巧,max
可以对任何可迭代对象进行操作,包括生成器。该行中的 lambda
关键字表示所谓的 "anonymous function"。
更多详细信息:匿名函数是未绑定到标识符的函数。代码段中的 Lambda 函数接受 1 个值,i
和 return 是矩阵位置 m[i][j]
处的绝对值。作为函数输入发送的值由生成器 xrange(j, n)
提供。
max
然后将 lambda 函数的 return 值作为它实际比较的对象。例如,在 python3 中无法比较 2 种不同的类型。 IE。比较 string > int 会产生:TypeError: unorderable types: str() > int()
。但是,如果我们确定该列表包含数字,只是格式不同,您可以执行以下操作:
>>> l = ["1", "2", 3, 4]
>>> max(l, key=lambda x: int(x))
4
>>> min(l, key=lambda x: int(x))
'1' #type 'str'
这只是表明,实际比较值是您的 key
函数的 return,但实际产生的值是您的原始输入值。
一旦它找到行最大值,它"rotates",通过替换ID[j], ID[row] = ID[row], ID[j]
,所有其他行,在单位矩阵,围绕它这样只有最大值留在对角线上。
这有助于防止在下一步的 LU 分解中除数过小。
您在 return 中得到的不是旋转后的原始矩阵,而是 1.0
s 和 0.0
s 的矩阵,即乘以original 将产生旋转矩阵。
这似乎是一个编写得很好的函数,可以节省内存并有助于 python 中的性能。希望我做对了。