简体   繁体   English

带lambda的min总是返回python中的第一个值吗?

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

In python 2.7.3, using the min function with a lambda, such as min(list, key=f) where f is an lambda function. 在python 2.7.3中,使用带有lambda的min函数,例如min(list, key=f) ,其中f是lambda函数。 If it was the case that f(x) was always the same value for all x in list, is it guaranteed that list[0] will be returned? 如果f(x)始终是列表中所有x的相同值,是否保证将返回list[0]

Thanks 谢谢

In CPython and PyPy yes. 在CPython和PyPy中是的。 You can see in the source code that the maxval is updated only if the current value is lower than the maxval . 你可以在看到源代码maxval只有当电流值大于下被更新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 is case of both: for min it's Py_LT and for max it's Py_GT . 注意,在CPython内部,同一函数( min_max )用于min()mix() ,唯一的区别是传递op是两种情况:对于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 PyPy , w_max_item and w_max_val are updated only if the item is the first item from the sequence or if it satisfies the condition as per the function chosen based on the value of implementation_of ("max" or "min"): 与PyPy相同的情况下w_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

As Ashwini writes in his excellent answer, the implementation of CPython is such that the first result will be returned in the case of a tie. 正如Ashwini在他的出色回答中所写的那样,CPython的实现使得第一个结果将在平局的情况下返回。 In the Python 3.4 documentation , this behavior is explicitly stated: Python 3.4文档中 ,明确说明了此行为:

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). 这与其他排序稳定性保留工具(如sorted(iterable,key = keyfunc)[0]和heapq.nsmallest(1,iterable,key = keyfunc))一致。

Unfortunately there is no such statement in the Python 2 documentation: min 's behavior upon encountering multiple minimal items is undefined as far as the documentation is concerned. 不幸的是,在Python 2文档中没有这样的声明:就文档而言,遇到多个最小项的min的行为是未定义的。 This means that the CPython interpreter makes no guarantee that this behavior will be around in future versions, though one might argue that since this functionality is so well-known and established it is a de facto aspect of the language. 这意味着CPython解释器不能保证在将来的版本中会出现这种行为,尽管人们可能会争辩说,由于这个功能是如此众所周知并且已经建立,因此它是该语言的事实上的一个方面。

If you'd like to be really careful and explicit, you can define a function that is guaranteed to find the first minimum according to the Python 2 API: 如果你想非常小心和明确,你可以定义一个函数,保证根据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]

Whether or not you use it over the built-in min depends upon how seriously you regard sticking to the defined and documented behavior. 您是否在内置min使用它取决于您对严格遵守已定义和记录的行为的重视程度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM