在python 2.7.3中,使用带有lambda的min函数,例如min(list, key=f)
,其中f
是lambda函数。如果f(x)
列表中的所有x
的值始终相同,是否可以保证会返回list[0]
?
由于
答案 0 :(得分:5)
在CPython和PyPy中是的。您可以在source code中看到maxval
仅在当前值低于maxval
时才会更新。请注意,在CPython内部,min_max
和min()
使用了相同的函数(mix()
),唯一的区别是op
passed是两种情况:for {{1它是min
和Py_LT
max
。
Py_GT
Same case with PyPy,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);
}
}
}
和w_max_item
仅在项目是序列中的第一项或者根据基于{的值选择的函数满足条件时更新{1}}(&#34; max&#34;或&#34; min&#34;):
w_max_val
答案 1 :(得分:0)
正如Ashwini在他的出色回答中写道的那样,CPython的实现是这样的,即在平局的情况下将返回第一个结果。在Python 3.4 documentation中,明确说明了这种行为:
如果多个项目最小,则该函数返回第一个项目 遇到。这与其他排序稳定性保持一致 排序(iterable,key = keyfunc)[0]和heapq.nsmallest(1, iterable,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
上使用它取决于您对严格遵守已定义和记录的行为的重视程度。