max、xrange和lambda函数在python中的结合使用

2024-07-01 06:58:51 发布

您现在位置: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用于在文本中定义一个函数,它只返回M_ij的值(I的值取决于for循环),但I是什么?在

xrange不是和range相似吗?但它在这里会返回什么呢?在

当与函数max结合时,会发生什么?我只是不知道max函数里面有什么东西在比较。在

抱歉,如果这个问题听起来很愚蠢。我对编程很陌生


Tags: thelambda函数代码inidfordef
2条回答

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交互的讨论。回答“什么是i?”,它是lambda函数的参数,i可以等效为x对于foo。(为清楚起见,分别生成abs(m[x][j])和{})。在

And isn't xrange similar to range?

是的。在python2中,xrange返回一个sequence对象,该对象只在需要时才延迟地计算下一个值。See this for more info。当整个循环时,range和{}将使用不同的实现产生相同的结果。在

But what does it return here?

第5行的xrange(n)将返回从0到(n-1)的整数值,而第6行的xrange(j, n)将返回从j到(n-1)的整数值。在

编辑

关于lambda的更多信息:

考虑一下如何取一个给定的数字序列,并将每个数字加倍。首先定义一个将一个数字x加倍并返回该值的函数。然后将该函数映射到序列的每个元素。在

# Traditional
def double(x): return x*2
print map(double, [1,2,3,4])         # [2, 4, 6, 8]

您也可以使用匿名(lambda)函数来执行相同的操作:

^{pr2}$

请注意,除了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(排他)的整数序列。在
  • 然后,这些整数中的每一个都作为参数“传递”给键参数中的函数。换句话说,它们在lambda函数中被用作i。lambda函数“返回”第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的内存效率。在range实际创建一个列表之前,for循环将遍历它。xrange但是它是一个生成器,这意味着它在被请求时一次输出1个值,而不创建完整的列表。在

ID实际上是一个单位矩阵。你就在那儿。这是一个很好的技巧,布尔值可以转换成值为1.0的浮点值。在

然后代码段遍历所有剩余的行,并在原始矩阵row = max(xrange(j, n), key=lambda i: abs(m[i][j]))中找到该行的最大值。注意这里还有第二个很好的诀窍,max可以对任何iterable对象进行操作,包括生成器。^该行中的{}关键字表示所谓的“匿名函数”。在

更详细地说:匿名函数是不绑定到标识符的函数。代码段中的Lambda函数接受1个值i,并在矩阵位置m[i][j]返回一个绝对值。作为函数输入发送的值由生成器xrange(j, n)提供。在

max然后取lambda函数的返回值作为它实际比较的值。例如,在python3中,不可能比较两种不同的类型。一、 e.比较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函数的返回值,而实际生成的值是原始输入值。在

一旦找到了行的最大值,它通过替换ID[j], ID[row] = ID[row], ID[j],将单位矩阵中的所有其他行围绕它“旋转”,这样只有最大值保留在对角线上。在

这有助于防止在LU分解的下一步中按太小的数字进行除法。在

你得到的不是原始矩阵,旋转的,而是一个1.0s和0.0s的矩阵,它是你的变换矩阵,乘以原始矩阵就会得到旋转矩阵。在

这似乎是一个编写得非常好的函数,它可以节省内存并有助于python的性能。希望我做得对。在

相关问题 更多 >

    热门问题