【问题标题】:Does min with lambda always return the first value in python?带有 lambda 的 min 是否总是返回 python 中的第一个值?
【发布时间】:2023-03-30 22:02:01
【问题描述】:

在 python 2.7.3 中,使用带有 lambda 的 min 函数,例如 min(list, key=f) 其中f 是一个 lambda 函数。如果f(x)对于列表中的所有x总是相同的值,是否保证list[0]会被返回?

谢谢

【问题讨论】:

  • 可能吗?取决于min 的实现。这真的很重要吗,因为您已经根据它们都是平等的事实来推断示例?
  • 在我的程序中,这很重要,它与代码的特定功能有关。尽管如此,我仍然想知道这是否属实。
  • @HunterMcMillen, f(0) == f(1) 但可能是l[0] != l[1]
  • @omega,我在解释 HunterMcMillen 为什么它可能很重要。

标签: python lambda


【解决方案1】:

在 CPython 和 PyPy 中是的。您可以在source code 中看到,仅当当前值低于maxval 时,maxval 才会更新。请注意,在 CPython 内部,min()mix() 都使用相同的函数(min_max),唯一的区别是op passed 是两者的情况:对于min,它是Py_LT,对于@987654333 @它是Py_GT

maxitem = NULL; /* the result */
maxval = NULL;  /* the value associated with the result */
while (( item = PyIter_Next(it) )) {
    /* get the value from the key function */
    if (keyfunc != NULL) {
        val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL);
        if (val == NULL)
            goto Fail_it_item;
    }
    /* no key function; the value is the item */
    else {
        val = item;
        Py_INCREF(val);
    }

    /* maximum value and item are unset; set them */
    if (maxval == NULL) {
        maxitem = item;
        maxval = val;
    }
    /* maximum value and item are set; update them as necessary */
    else {
        int cmp = PyObject_RichCompareBool(val, maxval, op);
        if (cmp < 0)
            goto Fail_it_item_and_val;
        else if (cmp > 0) {
            Py_DECREF(maxval);
            Py_DECREF(maxitem);
            maxval = val;
            maxitem = item;
        }
        else {
            Py_DECREF(item);
            Py_DECREF(val);
        }
    }
}

Same case with PyPyw_max_itemw_max_val 仅在项目是序列中的第一项或满足根据基于 implementation_of("max" 的值选择的函数的条件时更新或“分钟”):

if not has_item or \
        space.is_true(compare(w_compare_with, w_max_val)):
    has_item = True
    w_max_item = w_item
    w_max_val = w_compare_with

【讨论】:

  • 什么是CPython?。我正在使用的 python 在 linux 机器上。
  • @omega 是 Python 的一个实现(默认)。
  • 鉴于这是未记录的事实,我们是否应该避免编写假定 CPython 以这种方式运行的 Python 代码?我怀疑实现是否会以会破坏这种行为的方式发生变化(它现在本质上是 API 的事实上的一部分),但我猜这不是保证。
  • 啊!在 Python 2 中这是未记录的,但在 Python 3.4 中,我们有 this:“如果多个项目最少,则函数返回遇到的第一个。”
【解决方案2】:

正如 Ashwini 在其出色的回答中所写,CPython 的实现是这样的,即在平局的情况下将返回第一个结果。在Python 3.4 documentation 中,明确说明了这种行为:

如果多个项目是最小的,该函数返回第一个 遭遇。这与其他排序稳定性保持一致 诸如 sorted(iterable, key=keyfunc)[0] 和 heapq.nsmallest(1, 可迭代,key=keyfunc)。

不幸的是,Python 2 文档中没有这样的声明:就文档而言,min 在遇到多个最小项目时的行为是未定义的。这意味着 CPython 解释器不保证这种行为会在未来的版本中出现,尽管有人可能会争辩说,由于这个功能是如此众所周知并被确立,它是该语言的一个事实上方面.

如果您想真正小心而明确,您可以定义一个保证根据 Python 2 API 找到第一个最小值的函数:

def first_min(iterable, **kwargs):
    wrapped = ((x,i) for i,x in enumerate(x))
    if "key" in kwargs:
        keyfun = kwargs["key"]
        kwargs["key"] = lambda x: (keyfun(x[0]), x[1])
    return min(wrapped, **kwargs)[0]

您是否在内置 min 上使用它取决于您对坚持已定义和记录的行为的重视程度。

【讨论】:

    猜你喜欢
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 2022-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多