带有 lambda 的 min 是否总是 return python 中的第一个值?

Does min with lambda always return the first value in python?

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

谢谢

在 CPython 和 PyPy 中是。您可以在 source code that the maxval is updated only if the current value is lower than the maxval. Note that internally in CPython same function(min_max) is being used for both min() and mix(), the only difference is the op passed 中看到两者的情况:对于 min 它是 Py_LT 而对于 max 它是 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" 或 "min"):

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

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

If multiple items are minimal, the function returns the first one encountered. This is consistent with other sort-stability preserving tools such as sorted(iterable, key=keyfunc)[0] and heapq.nsmallest(1, iterable, key=keyfunc).

不幸的是,Python2 文档中没有这样的声明:就文档而言,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 上使用它取决于您对坚持定义和记录的行为的重视程度。