【问题标题】:the use of combining max, xrange and lambda function in python在 python 中结合使用 max、xrange 和 lambda 函数
【发布时间】:2015-05-06 05:01:09
【问题描述】:

我找到了一个旋转方阵以进行 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 的值后返回 M_ij 的值(并且 j 的值取决于 for 循环),但是 i 是什么?

xrange 不是类似于 range 吗?但它在这里返回了什么?

当与函数 max 结合时,会发生什么?我只是不知道正在比较的 max 函数中的内容是什么。

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

【问题讨论】:

  • i 来自xrange(j, n)

标签: python lambda max xrange matrix-decomposition


【解决方案1】:

首先,ID 的行不就是单位矩阵吗?

是的。

其次,我真的无法理解行的行......

See this 讨论 max/key/lambda 交互。要回答“i 是什么?”,它是 lambda 函数的参数,i 可以等效为 x 用于 foo。 (为清楚起见,分别生成 abs(m[x][j]) 和 abs(m[foo][j]))。

xrange 不是类似于 range 吗?

是的。在 Python 2 中,xrange 返回一个序列对象,该对象仅在需要时才延迟计算下一个值。 See this for more info。当整个循环时,range 和 xrange 将产生相同的结果,但实现不同。

但它在这里返回了什么?

第 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) 函数来做同样的事情:

# Lambda
print map(lambda i: i*2, [1,2,3,4])  # [2, 4, 6, 8]

请注意,除了 double 函数的定义消失了,并且在对 map 的调用中对函数的引用被“内联” lambda 函数替换之外,一切都是一样的。

编辑 2

当与函数 max 结合时,会发生什么?

这行row = max(xrange(j, n), key=lambda i: abs(m[i][j]))可以分解如下:

  • xrange(j,n) 生成从j(包括)到n(不包括)的整数序列。
  • 然后,这些整数中的每一个都作为参数“传递”给键参数中的函数。换句话说,它们都被用作 lambda 函数中的i。 lambda 函数“返回”ith 行和jth 列的绝对值。[1]
  • max 函数然后找到这些“lambda 输出”的最大值并将 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] 这里有一些假设,但行列是表达矩阵的标准方式。

【讨论】:

  • 我知道 'i' 是 lambda 函数的参数,但 'where' 是 i 吗?通常在我定义一个函数(比如 y=np.sin(t))之后,我会将 t=np.linspace(0,2*np.pi) 声明为参数,但现在我只是感到困惑,因为没有t 任何其他与我相关的代码...
  • re:您的评论编辑 -- i 不比 x 在 double 函数的定义中更丰富:double(x):
  • @Physicist: i 只是传递给key 函数的参数的任意名称,其返回值决定了max() 函数使用的顺序。在这种情况下,它将是一个整数,其值从 j 到 n-1(含),因为 xrange(j, n)。
  • 请注意,由于max 可以采用任何可迭代的,甚至是生成器表达式,您可以编写row = max( abs(m[i][j]) for i in xrange(j,n) ) 并保存创建一个实际的list,因为列表理解。
【解决方案2】:

xrange 是一个 Python2 构造,用于处理range 内存效率。在range 之前实际上创建了一个列表,然后for 循环将通过它运行。 xrange 但是是一个生成器,这意味着它在被要求时一次吐出 1 个值,而不创建完整列表。

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

然后sn-p遍历所有剩余的行,并在原始矩阵row = max(xrange(j, n), key=lambda i: abs(m[i][j]))中找到该行的最大值。请注意,这里有第二个不错的技巧,max 可以对任何可迭代对象进行操作,包括生成器。该行中的lambda 关键字表示所谓的“匿名函数”。

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

max 然后将 lambda 函数的返回值作为它实际比较的值。例如,在 python3 中,无法比较 2 种不同的类型。 IE。比较字符串 > 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 的性能。希望我做对了。

【讨论】:

    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 2016-07-24
    • 2021-02-23
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多